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

# Credits API - Check Team Balances and Transfer Credits

> Monitor credit balances across your team hierarchy and transfer credits between parent and child teams using the Examino Credits API.

The Credits API gives you programmatic control over Examino's credit system. Credits are consumed each time a copy is processed, the cost depends on page count, not the number of questions. You can use this API to monitor balances across your team hierarchy and redistribute credits between parent and child teams without touching the dashboard.

<Note>
  **Credit pricing model:** Cost is volumetric, 1 credit per started 20-page block per copy. A 12-page copy costs **1 credit**; a 45-page copy (3 × 20-page blocks started) costs **3 credits**.
</Note>

## Get Credit Balance

<ParamField header="Authorization" type="string" required>
  Bearer token. Format: `Bearer $EXAMINO_API_KEY`
</ParamField>

<Note>
  Required scope: `credits:read`
</Note>

Returns the available credit balance for a specific team. Available credits include any credits held directly by the team **and** credits inherited from its ancestor teams.

### Query Parameters

<ParamField query="teamId" type="string" required>
  UUID of the team to query. Must be within your API key's scope (i.e., your root team or one of its descendants).
</ParamField>

### Request

```bash theme={null}
curl "https://app.examino.ai/api/v1/credits?teamId=d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9" \
  -H "Authorization: Bearer $EXAMINO_API_KEY"
```

### Response

```json theme={null}
{
  "teamId": "d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9",
  "availableCredits": 1840
}
```

### Response Fields

<ResponseField name="teamId" type="string">
  UUID of the team that was queried. Mirrors the `teamId` you passed as a query parameter.
</ResponseField>

<ResponseField name="availableCredits" type="integer">
  Total credits available to this team, including credits inherited from all ancestor teams up the hierarchy. This is the effective spendable balance, not the balance held at this node alone.
</ResponseField>

***

## Transfer Credits

<ParamField header="Authorization" type="string" required>
  Bearer token. Format: `Bearer $EXAMINO_API_KEY`
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`.
</ParamField>

<Note>
  Required scope: `credits:write`
</Note>

Moves a specified number of credits from one team to another. Transfers are atomic, the debit and credit happen in a single operation, so no partial transfer can leave your hierarchy in an inconsistent state.

### Request Parameters

<ParamField body="fromTeamId" type="string" required>
  UUID of the team to debit credits from. Must be within your API key's scope.
</ParamField>

<ParamField body="toTeamId" type="string" required>
  UUID of the team to credit. Must be within your API key's scope.
</ParamField>

<ParamField body="amount" type="integer" required>
  Number of credits to transfer. Must be a strictly positive integer (minimum: `1`).
</ParamField>

### Request

```bash theme={null}
curl -X POST https://app.examino.ai/api/v1/credits/transfers \
  -H "Authorization: Bearer $EXAMINO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fromTeamId": "6b0b1f1a-2c3d-4e5f-8a9b-0c1d2e3f4a5b",
    "toTeamId": "d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9",
    "amount": 500
  }'
```

### Response

```json theme={null}
{
  "fromTeamId": "6b0b1f1a-2c3d-4e5f-8a9b-0c1d2e3f4a5b",
  "toTeamId": "d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9",
  "amount": 500,
  "fromAvailableCredits": 3200,
  "toAvailableCredits": 2340
}
```

### Response Fields

<ResponseField name="fromTeamId" type="string">
  UUID of the team that was debited.
</ResponseField>

<ResponseField name="toTeamId" type="string">
  UUID of the team that was credited.
</ResponseField>

<ResponseField name="amount" type="integer">
  Number of credits that were transferred, as specified in the request.
</ResponseField>

<ResponseField name="fromAvailableCredits" type="integer">
  Updated available credit balance of the source team after the transfer completes.
</ResponseField>

<ResponseField name="toAvailableCredits" type="integer">
  Updated available credit balance of the destination team after the transfer completes.
</ResponseField>

### Transfer Rules

<AccordionGroup>
  <Accordion title="Transfers must follow the team hierarchy">
    You can only transfer credits between a team and one of its direct or indirect descendants, in either direction (parent → child or child → parent). Transfers between two sibling teams, or between teams in unrelated branches of the hierarchy, are not permitted.

    Violating this rule returns `422 Unprocessable Entity` with reason `notRelated`.

    ```json theme={null}
    {
      "error": "unprocessable",
      "reason": "notRelated",
      "message": "fromTeamId and toTeamId are not in a direct ancestor–descendant relationship"
    }
    ```
  </Accordion>

  <Accordion title="You must be an admin of both teams">
    The account that owns the API key must hold the **admin** role on both the source and destination teams. If the key owner has been removed from either team, or if the account no longer exists, the request is rejected.

    This returns `403 Forbidden`.

    ```json theme={null}
    {
      "error": "forbidden",
      "message": "API key owner must be admin of both fromTeamId and toTeamId"
    }
    ```
  </Accordion>

  <Accordion title="The source team must have sufficient balance">
    The `fromTeamId` team must hold enough credits to cover the full `amount`. If not, the entire transfer is rejected, no credits are moved. There are no partial debits.

    This returns `422 Unprocessable Entity` with reason `insufficient`.

    ```json theme={null}
    {
      "error": "unprocessable",
      "reason": "insufficient",
      "message": "fromTeamId does not have enough credits to complete this transfer"
    }
    ```

    <Warning>
      `availableCredits` from `GET /credits` includes inherited ancestor credits, which cannot be debited from a child team directly. To check the balance a team **holds** (and can transfer out), compare balances before and after a test or inspect your credit ledger in the dashboard.
    </Warning>
  </Accordion>
</AccordionGroup>

<Tip>
  To distribute a fresh credit purchase to several campus teams at once, make one `POST /credits/transfers` call per destination team. Each call is atomic, so a failure on one transfer won't affect the others.
</Tip>
