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

# Applying for a virtual card

> Issue a virtual card to a company or employee with apply: the full field reference (subjectType/cardProfileId matching, company-card custodian, ruleIds binding), the complete error codes, and querying progress, single cards and card lists with query-apply / query / list.

## 📄 Guide

Issuing always starts with a virtual card: `POST /open-api-corp/card/v1/apply` returns an `cardApplyId` on acceptance; risk checks and card creation run fully asynchronously, with the final state pushed via the webhooks `CARD_CREATED` / `CARD_REJECTED` and `GET /open-api-corp/card/v1/query-apply` as the polling fallback. Once the card is created, use the `cardId` for single-card and list queries. For where this chain sits among the card pages, see [Managing cards](./managing-cards).

## Applying for a virtual card

```http theme={null}
POST /open-api-corp/card/v1/apply
```

### Request parameters

| Field                 | Type            | Required    | Description                                                                                                                                                                                                                                                              |
| --------------------- | --------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `cardApplyRef`        | String          | Yes         | ≤64; your unique application identifier                                                                                                                                                                                                                                  |
| `subjectType`         | String          | Yes         | `ORGANIZATION` (company card) / `CUSTOMER` (employee card)                                                                                                                                                                                                               |
| `subjectId`           | String          | Yes         | ≤20; the holder's external id: `ORGANIZATION`→`organizationId`, `CUSTOMER`→`customerId`. Must exist, match the type, be ACTIVE and belong to your partnership                                                                                                            |
| `cardProfileId`       | String          | Yes         | The card type code — one of the four types (see the pairing table below for valid `subjectType` combinations)                                                                                                                                                            |
| `custodianCustomerId` | String          | Conditional | ≤20; required for company cards (`subjectType`≠`CUSTOMER`): the `customerId` of an employee of the same company, who must be ACTIVE                                                                                                                                      |
| `ruleIds`             | `Array<String>` | Conditional | ≤5 entries; velocity (amount/count limit) rules bound at issue time, each element a rule external id. Required for company-balance cards (the company-pool profiles, i.e. the company utility card and the corporate-funded employee card); optional for the other types |

### The four cardProfileId types and their subjectType pairing

A card type is the combination of two orthogonal dimensions: the holder (who the card is issued to) × the balance mode (which account the money comes from). For the full card-type introduction see [Overview · Card types](../getting-started/overview).

| Card type                         | `cardProfileId`                  | `subjectType`  | Balance mode               | Custodian (`custodianCustomerId`) |
| --------------------------------- | -------------------------------- | -------------- | -------------------------- | --------------------------------- |
| Company utility card              | `COMPANY_UTILITY_CARD`           | `ORGANIZATION` | company pool               | Required                          |
| Dedicated-purpose company card    | `COMPANY_DEDICATED_PURPOSE_CARD` | `ORGANIZATION` | card's own balance balance | Required                          |
| Employee card (company pool)      | `EMPLOYEE_CARD_CORPORATE_FUNDED` | `CUSTOMER`     | SHARED company pool        | Not applicable                    |
| Employee card (dedicated balance) | `EMPLOYEE_CARD_SELF_FUNDED`      | `CUSTOMER`     | DEDICATED balance          | Not applicable                    |

<Note>
  Per regulatory requirements, a company card must designate a current employee of the company as its custodian. The custodian is who gets contacted when something is wrong with the card, and who completes verification when a purchase triggers a 3DS challenge.
</Note>

### Binding rules with ruleIds

Every rule in `ruleIds` must simultaneously: **exist, belong to the same company, and be ACTIVE**; a rule that configures amount limits must share at least one currency with the card's settlement currencies. The array must not contain duplicates — carrying the same rule twice is rejected outright (it is not silently deduplicated), so deduplicate before submitting.

<Warning>
  **Any failing entry rejects the whole request** (an early rejection before acceptance — no `cardApplyId` is produced); there is no partial success. After issuance you can still adjust the targets through the velocity endpoints — see [Setting spend limits](./spend-limits).
</Warning>

### Request examples

```json theme={null}
// Scenario 1: employee card (company pool, SHARED — ruleIds required)
{
  "cardApplyRef": "ext-card-apply-0001",
  "subjectType": "CUSTOMER",
  "subjectId": "a3f8d2b1-6c94-4e07-b512-9d8e7f6a5b4c",
  "cardProfileId": "EMPLOYEE_CARD_CORPORATE_FUNDED",
  "ruleIds": ["5136744097353943556"]
}

// Scenario 2: company utility card (non-personalized — custodianCustomerId required; SHARED — ruleIds required)
{
  "cardApplyRef": "ext-card-apply-0002",
  "subjectType": "ORGANIZATION",
  "subjectId": "e7c9a1f0-3b52-4d8e-9a67-1f2b3c4d5e6f",
  "cardProfileId": "COMPANY_UTILITY_CARD",
  "custodianCustomerId": "a3f8d2b1-6c94-4e07-b512-9d8e7f6a5b4c",
  "ruleIds": ["5136744097353943556"]
}
```

### Response data and example

| Field         | Type   | Description                                                                                                                                                                                        |
| ------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cardApplyId` | String | The card application ID                                                                                                                                                                            |
| `status`      | String | On successful acceptance this endpoint always returns `PENDING` (the creation result is pushed asynchronously via webhook); the full application status enum is `PENDING` / `SUCCEED` / `REJECTED` |

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": null,
  "data": {
    "cardApplyId": "5136744097353943553",
    "status": "PENDING"
  }
}
```

### Error codes

| Error code                     | Description                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CARD_PROFILE_INVALID`         | Card type unavailable (e.g. invalid/disabled type code, not enabled for your partnership, or `subjectType` does not match the type's applicable holder); see message/reason for the specifics                                                                                                                                                                                               |
| `CARD_LIMIT_EXCEEDED`          | Over the card cap (company-level or holder-level; live cards and in-flight applications counted together); see message/reason for which level                                                                                                                                                                                                                                               |
| `SUBJECT_INVALID`              | Company-card custodian missing, or not a valid employee of the company                                                                                                                                                                                                                                                                                                                      |
| `SUBJECT_INVALID`              | The holder (company) does not exist or is invalid                                                                                                                                                                                                                                                                                                                                           |
| `CUSTOMER_INVALID`             | The holding/custodian employee does not exist or is invalid                                                                                                                                                                                                                                                                                                                                 |
| `DAPI_PERMISSION_DENIED`       | Partner does not exist or is not activated (the partner identity is derived from the AK; this is an authorization issue handled by the gateway authorization codes, HTTP 401; rarely seen)                                                                                                                                                                                                  |
| `APPLY_DUPLICATE`              | An in-flight or successful application already exists for this `cardApplyRef`; it cannot be resubmitted                                                                                                                                                                                                                                                                                     |
| `CARD_RULE_REQUIRED`           | A company-balance card carried no `ruleIds` (an empty array counts as none)                                                                                                                                                                                                                                                                                                                 |
| `CARD_RULE_DUPLICATE`          | The same rule appears more than once in `ruleIds`. It is not silently deduplicated — a duplicate usually means the caller's view of "which rules are actually bound" has drifted, and quietly collapsing it would leave you believing N rules were bound. Note: when the array both exceeds 5 entries and contains duplicates, this code is returned rather than `CARD_RULE_LIMIT_EXCEEDED` |
| `CARD_RULE_LIMIT_EXCEEDED`     | More than 5 entries in `ruleIds`                                                                                                                                                                                                                                                                                                                                                            |
| `CARD_RULE_INVALID`            | The rule does not exist, does not belong to this company, or is not ACTIVE — one code covers all three, so the response cannot be used to probe whether a rule exists under another company; see message for the specifics                                                                                                                                                                  |
| `CARD_RULE_CURRENCY_NOT_MATCH` | The rule's amount-limit currencies share no currency with the card's settlement currencies                                                                                                                                                                                                                                                                                                  |

Related webhooks: `CARD_CREATED` / `CARD_REJECTED`.

## Querying application progress

```http theme={null}
GET /open-api-corp/card/v1/query-apply?cardApplyId=5136744097353943553
```

The only request parameter is `cardApplyId` (String, required, ≤20; the card application ID).

**Response data**:

| Field          | Type   | Description                                                                                                            |
| -------------- | ------ | ---------------------------------------------------------------------------------------------------------------------- |
| `cardApplyId`  | String | The application ID                                                                                                     |
| `status`       | String | The full application status enum: `PENDING` (in acceptance / card creation) / `SUCCEED` / `REJECTED`                   |
| `cardId`       | String | The card ID once created (empty before creation)                                                                       |
| `errorCode`    | String | The rejection code: fixed at `CARD_RISK_REJECTED` (only when `REJECTED`)                                               |
| `errorMessage` | String | The rejection reason: fixed at `risk check refused` (only when `REJECTED`; internal risk codes are not passed through) |

```json theme={null}
// Scenario 1: card created successfully
{
  "code": "SYS_SUCCESS",
  "message": null,
  "data": {
    "cardApplyId": "5136744097353943553",
    "status": "SUCCEED",
    "cardId": "5185740066240790530",
    "errorCode": null,
    "errorMessage": null
  }
}

// Scenario 2: rejected by risk
{
  "code": "SYS_SUCCESS",
  "message": null,
  "data": {
    "cardApplyId": "5136744097353943553",
    "status": "REJECTED",
    "cardId": null,
    "errorCode": "CARD_RISK_REJECTED",
    "errorMessage": "risk check refused"
  }
}
```

Error code: `APPLY_NOT_FOUND` — the application does not exist (or does not belong to your partnership).

## Querying a single card

```http theme={null}
GET /open-api-corp/card/v1/query?cardId=5185740066240790530
```

The only request parameter is `cardId` (String, required, ≤20; the card ID).

**Response data**:

| Field            | Type   | Description                                                                                                                                       |
| ---------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cardId`         | String | The card ID                                                                                                                                       |
| `panFirst6`      | String | First 6 digits of the PAN (the BIN; the full PAN is never returned)                                                                               |
| `panLast4`       | String | Last 4 digits of the PAN (the full PAN is never returned)                                                                                         |
| `organizationId` | String | The owning company                                                                                                                                |
| `subjectType`    | String | `ORGANIZATION` / `CUSTOMER`                                                                                                                       |
| `subjectId`      | String | The holder's external id                                                                                                                          |
| `cardProfileId`  | String | The card product code: `COMPANY_UTILITY_CARD` / `COMPANY_DEDICATED_PURPOSE_CARD` / `EMPLOYEE_CARD_CORPORATE_FUNDED` / `EMPLOYEE_CARD_SELF_FUNDED` |
| `cardNetwork`    | String | `VISA` / `MASTERCARD` / `UPI`                                                                                                                     |
| `currency`       | String | `USD` / `HKD`                                                                                                                                     |
| `status`         | String | Card status: `ACTIVE` / `FROZEN` / `LOCKED` / `RESTRICTED` / `LOST` / `EXPIRED` / `CLOSED`                                                        |

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": null,
  "data": {
    "cardId": "5185740066240790530",
    "panFirst6": "520983",
    "panLast4": "5492",
    "organizationId": "e7c9a1f0-3b52-4d8e-9a67-1f2b3c4d5e6f",
    "subjectType": "CUSTOMER",
    "subjectId": "a3f8d2b1-6c94-4e07-b512-9d8e7f6a5b4c",
    "cardProfileId": "EMPLOYEE_CARD_CORPORATE_FUNDED",
    "cardNetwork": "MASTERCARD",
    "currency": "USD",
    "status": "ACTIVE"
  }
}
```

Error code: `CARD_INVALID` — the card does not exist / does not belong to your partnership / is not ACTIVE.

## Listing cards

```http theme={null}
GET /open-api-corp/card/v1/list?organizationId=e7c9a1f0-3b52-4d8e-9a67-1f2b3c4d5e6f&subjectType=EMPLOYEE&status=ACTIVE&page=1&pageSize=20
```

A paginated query over the cards under your partnership; all filters are optional:

| Field            | Type    | Required | Description                                                                                          |
| ---------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `organizationId` | String  | No       | ≤20; filter by owning company                                                                        |
| `subjectType`    | String  | No       | `ORGANIZATION` / `CUSTOMER`                                                                          |
| `subjectId`      | String  | No       | ≤20; filter by holder                                                                                |
| `status`         | String  | No       | Filter by card status: `ACTIVE` / `FROZEN` / `LOCKED` / `RESTRICTED` / `LOST` / `EXPIRED` / `CLOSED` |
| `page`           | Integer | No       | Starts at 1, default 1                                                                               |
| `pageSize`       | Integer | No       | 1\~100, default 20                                                                                   |

**Response data**: the paging envelope is `page` (current page, Integer), `pageSize` (page size, Integer), `total` (total count) and `result` (the cards); each element of `result` carries exactly the same fields as the single-card query response above (`cardId` / `panFirst6` / `panLast4` / `organizationId` / `subjectType` / `subjectId` / `cardProfileId` / `cardNetwork` / `cardProfileId` / `currency` / `status`).

## Next steps

* SHARED cards need bindable velocity rules before issuance: [Setting spend limits](./spend-limits)
* Display the PAN and CVV2 once the card is created: [Retrieving secure card details](./secure-card-details)
