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

# Issue Card

> Issue a new virtual card to a cardholder. POST /cards. Requires cards:write scope.

## Overview

Issue a virtual prepaid card to a cardholder under one of your programs. Pass `productId` — the program, card type, and spend limits are all derived from the product automatically.

<Warning>
  **Card issuance is asynchronous.** A successful response means the request was **accepted**; the card may be returned with status `CREATING` (no PAN yet) and becomes usable only once provisioning completes. If the response is delayed or times out, the card is still being created — poll [Get Card](/v3.20/api-reference/cards/get) until `status` is `ACTIVE` rather than treating the immediate response as final.
</Warning>

**JIT vs pre-funded cards:**

* **JIT-enabled products** (`features.hasJIT: true`): The card is funded on-demand at the point of each transaction. `amount` is optional.
* **Standard products** (`features.hasJIT: false`): The card requires an initial balance at issuance. `amount` is **required**.

## Request Body

| Field          | Type   | Required    | Description                                                                   |
| -------------- | ------ | ----------- | ----------------------------------------------------------------------------- |
| `cardholderId` | string | Yes         | The cardholder to issue the card to                                           |
| `productId`    | string | Yes         | The card product — program, card type, and spend limits are derived from this |
| `amount`       | number | Conditional | Initial balance in USD. Required when the product is not JIT-enabled          |
| `customName`   | string | No          | Card label. Defaults to the cardholder's full name                            |

## Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.fyatu.com/api/v3.20/cards \
    -H "Authorization: Bearer $FYATU_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "cardholderId": "chl_01HXYZ1234ABCDEF5678",
      "productId":    "prd_01HXYZ1111ABCDEF0001",
      "amount":       100.00,
      "customName":   "Travel Card"
    }'
  ```

  ```javascript Node.js theme={null}
  const resp = await fetch('https://api.fyatu.com/api/v3.20/cards', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FYATU_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      cardholderId: 'chl_01HXYZ1234ABCDEF5678',
      productId:    'prd_01HXYZ1111ABCDEF0001',
      amount:       100.00,
      customName:   'Travel Card'
    })
  });

  const body = await resp.json();
  const card = body.data;
  console.log('Card ID:', card.id);
  console.log('Expiry:', card.expirationDate);
  console.log('Balance:', card.balance, card.currency);
  ```

  ```python Python theme={null}
  import os, requests

  resp = requests.post(
      'https://api.fyatu.com/api/v3.20/cards',
      headers={'Authorization': f'Bearer {os.environ["FYATU_API_KEY"]}'},
      json={
          'cardholderId': 'chl_01HXYZ1234ABCDEF5678',
          'productId':    'prd_01HXYZ1111ABCDEF0001',
          'amount':       100.00,
          'customName':   'Travel Card'
      }
  )
  card = resp.json()['data']
  print('Card ID:', card['id'])
  print('Expiry:', card['expirationDate'])
  print('Balance:', card['balance'], card['currency'])
  ```
</CodeGroup>

## Success Response (201)

```json theme={null}
{
  "success": true,
  "status":  201,
  "message": "Card issued",
  "data": {
    "id":           "crd_01HXYZ5555ABCDEF1111",
    "cardholderId": "chl_01HXYZ1234ABCDEF5678",
    "productId":    "prd_01HXYZ1111ABCDEF0001",
    "status":       "ACTIVE",
    "cardType":     "VIRTUAL",
    "cardBrand":    "VISA",
    "maskedPan":    "445123******4123",
    "last4":        "4123",
    "createdAt":    "2026-05-26T10:00:00Z",
    "updatedAt":    "2026-05-26T10:00:00Z",
    "nameOnCard":     "Travel Card",
    "expirationDate": "06/2030",
    "balance":        100.00,
    "currency":       "USD",
    "features": {
      "has3DS":          true,
      "hasApplePay":     false,
      "hasGooglePay":    false,
      "hasJIT":          false,
      "hasSpendControl": true,
      "hasMccControl":   false,
      "isReloadable":    true,
      "isOneTimeUse":    false
    },
    "spendingLimit":  1000.00,
    "spendingPeriod": "TRANSAMOUNT",
    "billingAddress": {
      "address": "1234 Main St",
      "city":    "New York",
      "state":   "NY",
      "zipCode": "10001",
      "country": "US"
    }
  },
  "meta": {
    "requestId": "req_01HXY123456ABCDEF",
    "platform":  "Fyatu CaaS",
    "timestamp": "2026-05-26T10:00:00Z"
  }
}
```

## Response Fields

| Field                      | Type    | Description                                                                                                                 |
| -------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------- |
| `id`                       | string  | Card identifier (prefix `crd_`)                                                                                             |
| `cardholderId`             | string  | The cardholder this card belongs to                                                                                         |
| `productId`                | string  | The product the card was issued under                                                                                       |
| `status`                   | string  | Always `ACTIVE` at issuance                                                                                                 |
| `cardType`                 | string  | `VIRTUAL` or `PHYSICAL`                                                                                                     |
| `cardBrand`                | string  | `VISA` or `MASTERCARD`                                                                                                      |
| `maskedPan`                | string  | BIN-masked PAN — first 6 digits + 6 stars + last 4 (e.g. `445123******4123`)                                                |
| `last4`                    | string  | Last 4 digits of the PAN                                                                                                    |
| `createdAt`                | string  | ISO 8601 creation timestamp                                                                                                 |
| `updatedAt`                | string  | ISO 8601 last-update timestamp                                                                                              |
| `nameOnCard`               | string  | Name displayed on the card — `customName` if provided, otherwise the cardholder's full name                                 |
| `expirationDate`           | string  | Card expiry in `MM/YYYY` format (e.g. `06/2030`)                                                                            |
| `balance`                  | number  | Current card balance in USD                                                                                                 |
| `currency`                 | string  | Card currency (always `USD`)                                                                                                |
| `features`                 | object  | Card capability flags inherited from the product                                                                            |
| `features.has3DS`          | boolean | 3D Secure enabled                                                                                                           |
| `features.hasApplePay`     | boolean | Apple Pay tokenisation supported                                                                                            |
| `features.hasGooglePay`    | boolean | Google Pay tokenisation supported                                                                                           |
| `features.hasJIT`          | boolean | Just-In-Time funding enabled (no pre-fund required)                                                                         |
| `features.hasSpendControl` | boolean | Spend limit control active                                                                                                  |
| `features.hasMccControl`   | boolean | MCC (merchant category) control active                                                                                      |
| `features.isReloadable`    | boolean | Card can be topped up via `POST /cards/{id}/fund`                                                                           |
| `features.isOneTimeUse`    | boolean | Card terminates automatically after its first settled transaction                                                           |
| `spendingLimit`            | number  | Spend cap per `spendingPeriod` in USD, inherited from the product                                                           |
| `spendingPeriod`           | string  | Period over which the spend cap applies — `TRANSAMOUNT`, `DAILY`, `WEEKLY`, `MONTHLY`, `QUARTERLY`, `YEARLY`, or `LIFETIME` |
| `billingAddress`           | object  | Billing address registered with the card provider                                                                           |
| `billingAddress.address`   | string  | Street address                                                                                                              |
| `billingAddress.city`      | string  | City                                                                                                                        |
| `billingAddress.state`     | string  | State or region                                                                                                             |
| `billingAddress.zipCode`   | string  | Postal code                                                                                                                 |
| `billingAddress.country`   | string  | Two-letter ISO 3166-1 country code                                                                                          |

## Provisioning is asynchronous

The card provider provisions cards asynchronously. When you call `POST /cards`, the card may come back with **`status: "CREATING"`** and **empty `maskedPan`, `last4`, and `expirationDate`** — provisioning can take anywhere from a few seconds up to \~1 hour. The `201` response is an acknowledgement that the card was accepted, not a guarantee the card number is ready.

<Warning>
  If you store only the `cardId` from the `201`, **do not** read `maskedPan`/`last4`/`expirationDate` from that response — they may be blank. Use the **`CARD_ISSUED` webhook** (below) as the authoritative "card is ready" signal: it fires once, when provisioning completes, and always carries the finalized `maskedPan`, `last4`, and `expirationDate`. You can also poll `GET /cards/{id}` — a `CREATING` card returns `ACTIVE` with full details once ready.
</Warning>

## Webhook

The **`CARD_ISSUED`** event is fired **when the card finishes provisioning** (`CREATING` → `ACTIVE`) — immediately for instantly-provisioned cards, or later (up to \~1h) for cards that were `CREATING`. It always includes the complete card details:

```json theme={null}
{
  "event":      "CARD_ISSUED",
  "eventId":    "evt_01HXY123456ABCDEF",
  "businessId": "BUS1A2B3C4D5E6F",
  "environment": "LIVE",
  "timestamp":  "2026-05-26T10:00:00Z",
  "data": {
    "cardId":         "crd_01HXYZ5555ABCDEF1111",
    "status":         "ACTIVE",
    "cardType":       "VIRTUAL",
    "cardBrand":      "VISA",
    "cardholderId":   "chl_01HXYZ1234ABCDEF5678",
    "maskedPan":      "445123******4123",
    "last4":          "4123",
    "expirationDate": "06/2030",
    "balance":        100.00,
    "currency":       "USD",
    "is3ds":          true,
    "isTokenized":    false,
    "isJitfEnabled":  false
  }
}
```

## Error Codes

| Code                             | HTTP | Cause                                                                                                                        |
| -------------------------------- | ---- | ---------------------------------------------------------------------------------------------------------------------------- |
| `CARD_AMOUNT_REQUIRED`           | 400  | `amount` was not provided for a non-JIT product                                                                              |
| `INVALID_REQUEST`                | 400  | Missing required field or unsupported card type                                                                              |
| `CARDHOLDER_NOT_FOUND`           | 404  | Cardholder does not exist or belongs to another business                                                                     |
| `PRODUCT_NOT_FOUND`              | 404  | Product does not exist or belongs to another business                                                                        |
| `PROGRAM_NOT_FOUND`              | 404  | Program linked to the product not found                                                                                      |
| `PRODUCT_INACTIVE`               | 422  | Product is not active                                                                                                        |
| `PROGRAM_INACTIVE`               | 422  | Program is not active                                                                                                        |
| `CARDHOLDER_INACTIVE`            | 422  | Cardholder is suspended or terminated                                                                                        |
| `CARDHOLDER_KYC_NOT_APPROVED`    | 422  | Cardholder KYC is not `APPROVED` or `WAIVED`                                                                                 |
| `CARDHOLDER_CARD_LIMIT_EXCEEDED` | 409  | Cardholder has reached the `maxCardsPerCardholder` limit for this product                                                    |
| `PROVIDER_CREATE_FAILED`         | 422  | Card creation was rejected by the card provider                                                                              |
| `CARD_CREATION_UNAVAILABLE`      | 503  | Card creation is temporarily unavailable — either paused by Fyatu, or a transient processing issue on our side. Retry later. |
| `INSUFFICIENT_SCOPE`             | 403  | Key lacks `cards:write` scope                                                                                                |
| `INTERNAL_ERROR`                 | 500  | Server error                                                                                                                 |


## OpenAPI

````yaml v3.20/openapi.json POST /cards
openapi: 3.1.0
info:
  title: FYATU CaaS API v3.20
  description: >-
    FYATU Cards-as-a-Service API â€” API key authentication, Cardholder
    lifecycle, Card issuance, Transactions, Webhooks, and Programs.
  version: 3.20.0
  contact:
    name: FYATU Support
    url: https://fyatu.com
    email: support@fyatu.com
servers:
  - url: https://api.fyatu.com/api/v3.20
    description: >-
      FYATU CaaS API â€” the environment (LIVE or SANDBOX) is determined by the
      API key, not the URL
security:
  - BearerAuth: []
tags:
  - name: Meta
    description: Liveness, account info, and supported event types
  - name: Account
    description: Account-level balance and funding status
  - name: Programs
    description: Read card program configuration
  - name: Cardholders
    description: Create and manage cardholder profiles
  - name: Cards
    description: Issue, fund, freeze, and terminate virtual cards
  - name: Transactions
    description: Read-only card transaction history
  - name: Webhooks
    description: Manage webhook endpoints for real-time event delivery
  - name: Products
    description: Read card product configurations
paths:
  /cards:
    post:
      tags:
        - Cards
      summary: Issue a card
      description: >-
        Issue a virtual card to an approved cardholder. The program is derived
        from the product â€” pass `productId`, not `programId`. For non-JIT
        products, `amount` (initial balance in USD) is required; for JIT-enabled
        products it is optional.
      operationId: issueCard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - cardholderId
                - productId
              properties:
                cardholderId:
                  type: string
                  description: The cardholder to issue the card to
                  example: chl_01HXYZ1234ABCDEF5678
                productId:
                  type: string
                  description: >-
                    The card product â€” card type and program are derived from
                    this
                  example: prd_01HXYZ1111ABCDEF0001
                amount:
                  type: number
                  format: float
                  description: >-
                    Initial balance in USD. Required for non-JIT products;
                    optional for JIT-enabled products.
                  example: 100
                customName:
                  type: string
                  description: >-
                    Card label. Defaults to the cardholder's full name when
                    omitted.
                  example: Travel Card
      responses:
        '201':
          description: Card issued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardIssuanceResponse'
              example:
                success: true
                status: 201
                message: Card issued
                data:
                  id: crd_01HXYZ5555ABCDEF1111
                  cardholderId: chl_01HXYZ1234ABCDEF5678
                  productId: prd_01HXYZ1111ABCDEF0001
                  status: ACTIVE
                  cardType: VIRTUAL
                  cardBrand: VISA
                  maskedPan: 445123******4123
                  last4: '4123'
                  createdAt: '2026-05-26T10:00:00Z'
                  updatedAt: '2026-05-26T10:00:00Z'
                  nameOnCard: Travel Card
                  expirationDate: 06/2030
                  balance: 100
                  currency: USD
                  features:
                    has3DS: true
                    hasApplePay: false
                    hasGooglePay: false
                    hasJIT: false
                    hasSpendControl: true
                    hasMccControl: false
                    isReloadable: true
                    isOneTimeUse: false
                  spendingLimit: 1000
                  spendingPeriod: TRANSAMOUNT
                  billingAddress:
                    address: 1234 Main St
                    city: New York
                    state: NY
                    zipCode: '10001'
                    country: US
                meta:
                  requestId: req_01HXY123456ABCDEF
                  platform: Fyatu CaaS
                  timestamp: '2026-05-26T10:00:00Z'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: Cardholder not eligible
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                kycNotApproved:
                  value:
                    success: false
                    status: 422
                    message: Cardholder KYC is not approved
                    error:
                      code: CARDHOLDER_KYC_NOT_APPROVED
                      detail: Cardholder KYC is not approved
                    meta:
                      requestId: req_a1b2c3d4e5f6a7b8c9d0e1f2
                      platform: Fyatu CaaS
                      timestamp: '2026-05-22T15:00:00Z'
                notActive:
                  value:
                    success: false
                    status: 422
                    message: Cardholder is not active
                    error:
                      code: CARDHOLDER_INACTIVE
                      detail: Cardholder is not active
                    meta:
                      requestId: req_a1b2c3d4e5f6a7b8c9d0e1f2
                      platform: Fyatu CaaS
                      timestamp: '2026-05-22T15:00:00Z'
                amountRequired:
                  value:
                    success: false
                    status: 400
                    message: amount is required for non-JIT products
                    error:
                      code: CARD_AMOUNT_REQUIRED
                      detail: amount is required for non-JIT products
                    meta:
                      requestId: req_a1b2c3d4e5f6a7b8c9d0e1f2
                      platform: Fyatu CaaS
                      timestamp: '2026-05-22T15:00:00Z'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    CardIssuanceResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        status:
          type: integer
          example: 201
        message:
          type: string
          example: Card issued
        data:
          $ref: '#/components/schemas/CardIssuance'
        meta:
          $ref: '#/components/schemas/Meta'
    Error:
      type: object
      properties:
        success:
          type: boolean
          example: false
        status:
          type: integer
          example: 422
        message:
          type: string
          example: Human readable message
        error:
          $ref: '#/components/schemas/ErrorBody'
        meta:
          $ref: '#/components/schemas/Meta'
    CardIssuance:
      type: object
      description: >-
        Card object returned at issuance. Also includes the one-time CVV —
        identical to GET /cards/{id} except nameOnCard is only present here.
      properties:
        id:
          type: string
          example: crd_01HXYZ5555ABCDEF1111
        cardholderId:
          type: string
          example: chl_01HXYZ1234ABCDEF5678
        productId:
          type: string
          example: prd_01HXYZ1111ABCDEF0001
        status:
          type: string
          enum:
            - ACTIVE
          example: ACTIVE
        cardType:
          type: string
          enum:
            - VIRTUAL
            - PHYSICAL
          example: VIRTUAL
        cardBrand:
          type: string
          enum:
            - VISA
            - MASTERCARD
          example: VISA
        maskedPan:
          type: string
          nullable: true
          example: 421356******4242
        last4:
          type: string
          nullable: true
          example: '4242'
        createdAt:
          type: string
          format: date-time
          example: '2026-05-26T10:00:00Z'
        updatedAt:
          type: string
          format: date-time
          example: '2026-05-26T10:00:00Z'
        nameOnCard:
          type: string
          description: >-
            Name displayed on the card — customName if provided, otherwise the
            cardholder's full name
        expirationDate:
          type: string
          description: Card expiry in MM/YYYY format (e.g. 06/2030)
          example: 05/29
        balance:
          type: number
          format: float
          description: Current card balance in USD
          example: 100
        currency:
          type: string
          example: USD
        features:
          type: object
          description: Product-level feature flags at issuance time
          properties:
            has3DS:
              type: boolean
              description: 3D Secure enabled on the product
            hasApplePay:
              type: boolean
              description: Apple Pay tokenisation supported
            hasGooglePay:
              type: boolean
              description: Google Pay tokenisation supported
            hasJIT:
              type: boolean
              description: Just-In-Time funding enabled
            hasSpendControl:
              type: boolean
              description: Spend limit control active
            hasMccControl:
              type: boolean
              description: MCC control active
            isReloadable:
              type: boolean
              description: Card can be topped up via POST /cards/{id}/fund
            isOneTimeUse:
              type: boolean
              description: >-
                Card terminates automatically after its first settled
                transaction
        spendingLimit:
          type: number
          format: float
          description: Spend cap per spendingPeriod in USD
          example: 1000
        spendingPeriod:
          type: string
          enum:
            - TRANSAMOUNT
            - DAILY
            - WEEKLY
            - MONTHLY
            - QUARTERLY
            - YEARLY
            - LIFETIME
          example: TRANSAMOUNT
        billingAddress:
          type: object
          nullable: true
          properties:
            address:
              type: string
            city:
              type: string
            state:
              type: string
            zipCode:
              type: string
            country:
              type: string
    Meta:
      type: object
      properties:
        requestId:
          type: string
          example: req_a1b2c3d4e5f6a7b8c9d0e1f2
        platform:
          type: string
          example: Fyatu CaaS
        timestamp:
          type: string
          format: date-time
          example: '2026-05-22T15:00:00Z'
    ErrorBody:
      type: object
      properties:
        code:
          type: string
          example: VALIDATION_ERROR
        detail:
          type: string
          example: dateOfBirth must be in YYYY-MM-DD format
  responses:
    ValidationError:
      description: Request validation failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            status: 422
            message: Validation failed
            error:
              code: VALIDATION_ERROR
              detail: dateOfBirth must be in YYYY-MM-DD format
            meta:
              requestId: req_a1b2c3d4e5f6a7b8c9d0e1f2
              platform: Fyatu CaaS
              timestamp: '2026-05-22T15:00:00Z'
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missing:
              summary: API key missing
              value:
                success: false
                status: 401
                message: API key is required
                error:
                  code: AUTH_TOKEN_MISSING
                  detail: API key is required
                meta:
                  requestId: req_a1b2c3d4e5f6a7b8c9d0e1f2
                  platform: Fyatu CaaS
                  timestamp: '2026-05-22T15:00:00Z'
            invalid:
              summary: API key invalid
              value:
                success: false
                status: 401
                message: Invalid API key
                error:
                  code: AUTH_TOKEN_INVALID
                  detail: Invalid API key
                meta:
                  requestId: req_a1b2c3d4e5f6a7b8c9d0e1f2
                  platform: Fyatu CaaS
                  timestamp: '2026-05-22T15:00:00Z'
    Forbidden:
      description: Scope denied or business suspended
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            status: 403
            message: Scope denied
            error:
              code: INSUFFICIENT_SCOPE
              detail: This endpoint requires the cards:write scope
            meta:
              requestId: req_a1b2c3d4e5f6a7b8c9d0e1f2
              platform: Fyatu CaaS
              timestamp: '2026-05-22T15:00:00Z'
    NotFound:
      description: Resource not found or does not belong to your business
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimitExceeded:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            status: 429
            message: Rate limit exceeded
            error:
              code: RATE_LIMIT_EXCEEDED
              detail: Too many requests
            meta:
              requestId: req_a1b2c3d4e5f6a7b8c9d0e1f2
              platform: Fyatu CaaS
              timestamp: '2026-05-22T15:00:00Z'
    InternalError:
      description: Unexpected server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            status: 500
            message: Internal error
            error:
              code: INTERNAL_ERROR
              detail: An unexpected error occurred
            meta:
              requestId: req_a1b2c3d4e5f6a7b8c9d0e1f2
              platform: Fyatu CaaS
              timestamp: '2026-05-22T15:00:00Z'
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        API key from the FYATU CaaS portal. Pass as `Authorization: Bearer
        <key>`.

````