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

# Cards

> List cards and freeze or unfreeze them.

Card endpoints live under `/developer/company`. Every request needs `Authorization: Bearer <access_token>` and `X-On-Behalf-Of: <company_id>` — see [Authentication](/guides/authentication).

Reading cards needs no specific permission beyond company membership. **Freezing and unfreezing require the `manage_cards` permission**, which owners, admins, and employees hold by default.

## Endpoints

| Method | Path                                    | Purpose                             |
| ------ | --------------------------------------- | ----------------------------------- |
| `GET`  | `/developer/company/v2/card`            | List cards with filters and paging. |
| `GET`  | `/developer/company/v2/card/{id}`       | Fetch one card.                     |
| `POST` | `/developer/company/card/{id}/freeze`   | Freeze one card.                    |
| `POST` | `/developer/company/card/{id}/unfreeze` | Unfreeze one card.                  |

Use the `v2` paths for reads. The older `GET /developer/company/card` list is also reachable but returns a different shape and is not documented here.

## List cards

```bash theme={null}
curl -sS "https://api.incard.com/developer/company/v2/card?status=active,frozen&take=50" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-On-Behalf-Of: YOUR_COMPANY_ID"
```

Response (truncated):

```json theme={null}
{
  "data": [
    {
      "id": "3f8b2c1d-9e4a-4b7c-8d2e-1f3a5b7c9d0e",
      "token": "84de8ea0-e52a-4888-afd2-9d8dd5a42c20",
      "name": "Marketing spend",
      "type": "virtual",
      "lastFour": "4242",
      "expiryDate": "07/29",
      "status": "active",
      "user": { "id": "29b297ca-…", "firstName": "Alex", "lastName": "Example" },
      "spendingLimit": { "type": "monthly", "amount": 5000, "amountSpent": 1249.5, "utilization": 24.99 },
      "companyAccount": { "id": "0d6c0a2a-…", "name": "Main GBP account", "currencyCode": "GBP" },
      "currencyCode": "GBP"
    }
  ],
  "meta": { "total": 1, "totalPending": 0, "totalNonPending": 1, "take": 50, "skip": 0 }
}
```

Cards are returned newest first. Terminated cards are excluded unless you pass `includeTerminated=true` or ask for them in `status`.

### Filters and paging

| Parameter           | Notes                                                                                                            |
| ------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `take`, `skip`      | Page size (default 10, max 100) and offset. `meta.total` gives the full count.                                   |
| `type`              | `physical` or `virtual`.                                                                                         |
| `status`            | Comma-separated: `active`, `pending`, `frozen`, `expired`, `terminated`. `expired` is derived from `expiryDate`. |
| `userIds`           | Comma-separated user UUIDs the cards are assigned to.                                                            |
| `companyAccountIds` | Comma-separated account UUIDs the cards draw from.                                                               |
| `search`            | Case-insensitive match on card name or last four digits.                                                         |
| `sort`              | `unactivatedFirst` lists `pending` cards before the rest.                                                        |

Invalid values return **400** with `{ "error": "<field>: <message>" }`.

## Get a card

```bash theme={null}
curl -sS "https://api.incard.com/developer/company/v2/card/3f8b2c1d-9e4a-4b7c-8d2e-1f3a5b7c9d0e" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-On-Behalf-Of: YOUR_COMPANY_ID"
```

Returns the same card object as a list item, without the `data` wrapper. Unknown or other-company cards return **404** with `{ "error": "Card not found" }`.

## Card status

| Status       | Meaning                                                   | Can freeze?    | Can unfreeze?  |
| ------------ | --------------------------------------------------------- | -------------- | -------------- |
| `pending`    | Issued but not yet activated.                             | No             | No             |
| `active`     | Usable.                                                   | Yes            | Already active |
| `frozen`     | Frozen by a team member. New authorisations are declined. | Already frozen | Yes            |
| `blocked`    | Blocked by Incard. Contact support.                       | No             | No             |
| `closing`    | Being closed.                                             | No             | No             |
| `terminated` | Permanently cancelled.                                    | No             | No             |

Only a `frozen` card can be unfrozen through the API.

## Freeze a card

```bash theme={null}
curl -sS -X POST "https://api.incard.com/developer/company/card/3f8b2c1d-9e4a-4b7c-8d2e-1f3a5b7c9d0e/freeze" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-On-Behalf-Of: YOUR_COMPANY_ID"
```

No request body. The response is the stored card record with `status` now `frozen`:

```json theme={null}
{
  "id": "3f8b2c1d-9e4a-4b7c-8d2e-1f3a5b7c9d0e",
  "companyId": "bebb185d-8210-4e66-ac63-397b49a1e09f",
  "name": "Marketing spend",
  "token": "84de8ea0-e52a-4888-afd2-9d8dd5a42c20",
  "type": "virtual",
  "status": "frozen",
  "lastFour": "4242",
  "updatedAt": "2026-09-02T11:15:27.000Z"
}
```

The action is idempotent. Freezing a card that is already `frozen` returns **200** with the unchanged record.

## Unfreeze a card

```bash theme={null}
curl -sS -X POST "https://api.incard.com/developer/company/card/3f8b2c1d-9e4a-4b7c-8d2e-1f3a5b7c9d0e/unfreeze" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-On-Behalf-Of: YOUR_COMPANY_ID"
```

Returns the card record with `status` back to `active`. Unfreezing a card that is already `active` returns **200** unchanged.

## Errors

Card actions report problems in a common envelope:

```json theme={null}
{
  "severity": "warning",
  "path": "/api/company/card/3f8b2c1d-9e4a-4b7c-8d2e-1f3a5b7c9d0e/unfreeze",
  "status": 400,
  "reason": "Card has invalid source status for this action",
  "method": "POST"
}
```

| Status | `reason`                                         | Cause                                              |
| ------ | ------------------------------------------------ | -------------------------------------------------- |
| 400    | `Card not found`                                 | The UUID does not match a card in this company.    |
| 400    | `Card has invalid status for this action`        | Freeze attempted on a card that is not `active`.   |
| 400    | `Card has invalid source status for this action` | Unfreeze attempted on a card that is not `frozen`. |
| 403    | `Not permitted`                                  | The API key's member lacks `manage_cards`.         |
