## Card API Documentation

> **Recommended:** You can use [infini-skill](https://github.com/infini-money/infini-skill) to integrate with Infini APIs faster. The skill provides ready-to-use integration capabilities for the card API before you implement the raw requests below.


Card endpoints are used to apply for, list, query, batch-query statuses, retrieve transactions, reveal, top up, redeem, freeze, and unfreeze organization cards issued to your members.

All Card API prefix:

`/v2/cards`

### Card Identifier

The only card identifier merchants use is the internal **`id`**:

- **`data.id`** from **`POST /v2/cards/apply`**
- **`cards[].id`** from **`GET /v2/cards/list`**
- The **`id`** passed to **`GET /v2/cards/status`**, **`GET /v2/cards/transactions`**, **`POST /v2/cards/reveal`**, **`POST /v2/cards/top-up`**, **`POST /v2/cards/redeem`**, **`POST /v2/cards/freeze`**, and **`POST /v2/cards/unfreeze`**
- The values in **`card_ids`** passed to **`POST /v2/cards/status/batch`**


### Authentication and Permissions

All endpoints use HMAC-SHA256 authentication with **`Date`**, **`Digest`** when the request has a body, and **`Authorization`** with **`keyId`**. See [Chapter 4: Authorization and Security Mechanisms](/docs/en/4-authorization).

| Permission | Endpoints |
|  --- | --- |
| `card.create` | `POST /v2/cards/apply`, `GET /v2/cards/list`, `GET /v2/cards/status`, `POST /v2/cards/status/batch`, `GET /v2/cards/transactions`, `POST /v2/cards/top-up`, `POST /v2/cards/redeem`, `POST /v2/cards/freeze`, `POST /v2/cards/unfreeze` |
| `card.reveal` | `POST /v2/cards/reveal` |


> **IP whitelist:** API keys that include `card.create` or `card.reveal` must be configured with a non-empty IP whitelist when created or updated in the merchant dashboard.


### Response Envelope

All endpoints use the standard `code` / `message` / `data` envelope. Business success is indicated by `code === 0`; a non-zero `code` indicates an error and `message` carries the details.

### Apply Card

**POST** /v2/cards/apply

Creates a card application and initial top-up flow for an organization member.

- **Required permission:** `card.create`


#### Request Body

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| product_id | integer | Yes | Card product ID. `1` = Infini Lite, `2` = Infini Pro, `102` = Infini AI |
| top_up_amount | string | Yes | Initial top-up amount, decimal string |
| token_type | string | Yes | Token type, for example `USDT` or `USDC` |
| user_email | string | Yes | Organization member business account email under this merchant |
| holder_name | string | Yes | Card holder name |
| card_alias | string | No | Optional card alias |


#### Product IDs

| product_id | Product |
|  --- | --- |
| `1` | Infini Lite |
| `2` | Infini Pro |
| `102` | Infini AI |


#### Request Example

```json
{
  "product_id": 1,
  "top_up_amount": "100.00",
  "token_type": "USDT",
  "user_email": "jane@example.com",
  "holder_name": "Jane Doe",
  "card_alias": "Travel card"
}
```

#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "id": "a441831c-a5c7-4bed-8f61-793738afd5bc",
    "status": "init",
    "total_top_up_amount": "100.00",
    "total_fee": "1.00",
    "total_pay_amount": "101.00",
    "message": ""
  }
}
```

### List Cards

**GET** /v2/cards/list

Returns a paginated list of organization cards for the merchant.

- **Required permission:** `card.create`


#### Query Parameters

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| status | string | No | Card status filter, comma-separated, for example `active,pending` |
| card_alias | string | No | Card alias filter |
| page | integer | No | Page number, starting at `1`; default `1` |
| page_size | integer | No | Items per page, max `100`; default `20` |


#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "cards": [
      {
        "id": "a441831c-a5c7-4bed-8f61-793738afd5bc",
        "mask": "411111******1111",
        "holder_name": "Jane Doe",
        "card_alias": "Travel card",
        "status": "active",
        "currency": "USD",
        "available_balance": "50.25",
        "user_id": "usr_01HXYZ",
        "created_at": 1714464000,
        "updated_at": 1714550400
      }
    ],
    "total": 1,
    "page": 1,
    "page_size": 20,
    "total_pages": 1
  }
}
```

### Get Card Status

**GET** /v2/cards/status?id={id}

Returns lifecycle status and summary fields for one card. After **`POST /v2/cards/apply`**, poll until **`status`** becomes **`active`**.

- **Required permission:** `card.create`


#### Query Parameters

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| id | string | Yes | Internal card `id` from apply or list |


#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "id": "a441831c-a5c7-4bed-8f61-793738afd5bc",
    "status": "pending",
    "card_alias": "Travel card",
    "mask": "",
    "holder_name": "Jane Doe",
    "currency": "USD",
    "available_balance": "0",
    "user_id": "usr_01HXYZ",
    "created_at": 1714464000,
    "updated_at": 1714464100
  }
}
```

### Batch Get Card Statuses

**POST** /v2/cards/status/batch

Returns lifecycle statuses for up to 100 cards. Results follow the request order.

- **Required permission:** `card.create`


#### Request Body

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| card_ids | array of strings | Yes | Internal card IDs from apply or list; from `1` to `100` items |


#### Request Example

```json
{
  "card_ids": [
    "a441831c-a5c7-4bed-8f61-793738afd5bc",
    "b552942d-b6d8-5cef-9062-804849bfe6cd"
  ]
}
```

#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "cards": [
      {
        "card_id": "a441831c-a5c7-4bed-8f61-793738afd5bc",
        "status": "active"
      },
      {
        "card_id": "b552942d-b6d8-5cef-9062-804849bfe6cd",
        "status": "pending"
      }
    ]
  }
}
```

### Get Card Transactions

**GET** /v2/cards/transactions?id={id}&page={page}&page_size={page_size}

Returns a paginated transaction list for one organization card. The response uses the merchant-facing card ID and does not expose provider transaction IDs.

- **Required permission:** `card.create`


#### Query Parameters

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| id | string | Yes | Internal card `id` from apply or list |
| page | integer | No | Page number, starting at `1`; default `1` |
| page_size | integer | No | Items per page, max `100`; default `20` |


#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "transactions": [
      {
        "card_id": "a441831c-a5c7-4bed-8f61-793738afd5bc",
        "type": "Consume",
        "amount": "12.34",
        "fee": "0.12",
        "status": "Completed",
        "currency": "USD",
        "merchant": "Example Store",
        "transaction_time": 1710000000,
        "transaction_currency": "EUR",
        "transaction_amount": "11.20",
        "created_at": 1710000001,
        "updated_at": 1710000002,
        "settled_at": 1710000003
      }
    ],
    "total": 1,
    "page": 1,
    "page_size": 20,
    "total_pages": 1
  }
}
```

### Reveal Card

**POST** /v2/cards/reveal

Returns the full PAN, CVV, and expiry. This is sensitive data; do not log or persist these values in client applications.

- **Required permission:** `card.reveal`


#### Request Body

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| id | string | Yes | Internal card `id` from apply or list |


#### Request Example

```json
{
  "id": "a441831c-a5c7-4bed-8f61-793738afd5bc"
}
```

#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "card_number": "4111111111111111",
    "cvv": "123",
    "expiration_mmyy": "1228",
    "card_currency": "USD"
  }
}
```

### Top Up Card

**POST** /v2/cards/top-up

Adds funds to an organization card.

- **Required permission:** `card.create`


#### Request Body

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| id | string | Yes | Internal card `id` from apply or list |
| amount | string | Yes | Top-up amount |
| token_type | string | Yes | Token type, for example `USDT` or `USDC` |
| note | string | No | Optional top-up note |


#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "tx_id": "tx_123",
    "card_balance": "150.25"
  }
}
```

### Redeem Card

**POST** /v2/cards/redeem

Redeems funds from an organization card.

- **Required permission:** `card.create`


#### Request Body

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| id | string | Yes | Internal card `id` from apply or list |
| amount | string | Yes | Redeem amount |
| token_type | string | Yes | Token type, for example `USDT` or `USDC` |
| note | string | No | Optional redeem note |


#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "tx_id": "tx_123",
    "card_balance": "80.25"
  }
}
```

### Freeze Card

**POST** /v2/cards/freeze

Freezes an organization card.

- **Required permission:** `card.create`


#### Request Body

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| id | string | Yes | Internal card `id` from apply or list |


#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "success": true,
    "message": "Card frozen"
  }
}
```

### Unfreeze Card

**POST** /v2/cards/unfreeze

Unfreezes an organization card.

- **Required permission:** `card.create`


#### Request Body

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| id | string | Yes | Internal card `id` from apply or list |


#### Response Example

```json
{
  "code": 0,
  "message": "",
  "data": {
    "success": true,
    "message": "Card unfrozen"
  }
}
```