> ## Documentation Index
> Fetch the complete documentation index at: https://www.octoparse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Batch grants

> Share multiple apps with multiple users in one call. Matrix semantics, idempotent.

**`POST`** `https://api-datahub.octoparse.com/v1/data-apps/batch/grants`

Authentication: API key required (`Authorization: Bearer <API Key>`).

Open multiple apps you own to multiple users in one call (matrix semantics, idempotent). Storage and effective rules match single-user grant. Each username is resolved once. `granted` counts only **new** pairs; pairs already on the list are skipped idempotently so you can tell “3 added, 2 already present”.

## Request

### Request body

<ParamField body="app_names" type="string[]" required>
  —
</ParamField>

<ParamField body="usernames" type="string[]" required>
  Username list.
</ParamField>

### Example request

```bash theme={null}
curl -X POST \
  -H "Authorization: Bearer $OCTOPARSE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"apps": ["carol/reviews-query", "carol/product-detail"], "usernames": ["dave", "erin"]}' \
  "https://api-datahub.octoparse.com/v1/data-apps/batch/grants"
```

## Response

### 200 success

```json theme={null}
{
  "data": {
    "granted": 3,
    "skipped": 1,
    "apps": [
      {
        "app": "carol/reviews-query",
        "ok": true
      },
      {
        "app": "carol/product-detail",
        "ok": true
      }
    ],
    "users": [
      {
        "username": "dave",
        "ok": true
      },
      {
        "username": "erin",
        "ok": true
      }
    ]
  }
}
```

The payload is wrapped in `data`. Fields:

<ResponseField name="granted" type="integer" required>
  Number of newly created grant pairs.
</ResponseField>

<ResponseField name="requested" type="integer" required>
  —
</ResponseField>

<ResponseField name="apps" type="object[]" required>
  Per-app processing result.

  <Expandable title="fields">
    <ResponseField name="app_name" type="string" required>
      —
    </ResponseField>

    <ResponseField name="ok" type="boolean" required>
      —
    </ResponseField>

    <ResponseField name="code" type="string">
      —
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="users" type="object[]" required>
  Per-user resolution result.

  <Expandable title="fields">
    <ResponseField name="username" type="string" required>
      —
    </ResponseField>

    <ResponseField name="ok" type="boolean" required>
      —
    </ResponseField>

    <ResponseField name="code" type="string">
      —
    </ResponseField>
  </Expandable>
</ResponseField>

### Errors

| HTTP | `code`         | `category`  | Description                 |
| ---- | -------------- | ----------- | --------------------------- |
| 401  | `unauthorized` | `forbidden` | Missing or invalid API key. |

Error responses use `{"error": {code, category, message, retryable}}`. See <a href="/docs/en/datahub/api/reference/introduction#errors">Errors</a>.

## Client libraries

The Python and JavaScript SDKs do not wrap this endpoint yet. Call REST directly.
