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

# Cards

> Create, lock/unlock, delete, and retrieve encrypted card secrets.

<Tip>
  Prerequisite: have a session token. See Authentication.
</Tip>

## Card lifecycle

```mermaid theme={null}
sequenceDiagram
  participant Backend as Your Backend
  participant MachinesAPI as Machines API

  Backend->>MachinesAPI: POST /cards
  MachinesAPI-->>Backend: cardId
  Backend->>MachinesAPI: PATCH /cards/{"{cardId}"} (lock/unlock, limit)
  MachinesAPI-->>Backend: updated card
  Backend->>MachinesAPI: DELETE /cards/{"{cardId}"}
  MachinesAPI-->>Backend: canceled
```

## API flows (step‑by‑step)

<Steps>
  <Step title="List cards">
    <b>Endpoint</b>

    : <a href="/api/cards/list" target="_blank" rel="noreferrer"><code>GET /cards</code></a>
  </Step>

  <Step title="Create a card">
    <b>Endpoint</b>

    : <a href="/api/cards/create" target="_blank" rel="noreferrer"><code>POST /cards</code></a>

    \
    <b>Body</b>

    : optional <code>encryptedName</code>

    (encrypted card label) and optional <code>limit</code>

    with <code>amountCents</code>

    and <code>frequency</code>

    .

    <br />

    <b>Tip</b>

    : To set a card label, call <a href="/api/encryption/encrypt" target="_blank" rel="noreferrer"><code>POST /encryption/encrypt</code></a>

    first and pass the returned <code>value</code>

    as <code>encryptedName</code>

    (see <a href="/encryption">Encryption</a>

    ).

    ```bash theme={null}
    curl -s \
      -H 'Authorization: Bearer <SESSION_TOKEN>' \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: <UUID>' \
      -d '{"limit": {"amountCents": 2500, "frequency": "perAuthorization"}}' \
      https://dev-api.machines.cash/partner/v1/cards
    ```
  </Step>

  <Step title="Update status or limits">
    <b>Endpoint</b>

    : <a href="/api/cards/update" target="_blank" rel="noreferrer"><code>PATCH /cards/{"{cardId}"}</code></a>
  </Step>

  <Step title="Delete a card">
    <b>Endpoint</b>

    : <a href="/api/cards/delete" target="_blank" rel="noreferrer"><code>DELETE /cards/{"{cardId}"}</code></a>
  </Step>

  <Step title="Create a card secrets session (optional)">
    <b>Endpoint</b>

    : <a href="/api/cards/secrets/session" target="_blank" rel="noreferrer"><code>POST /cards/secrets/session</code></a>

    <br />

    <b>Body</b>

    : send an empty JSON object if your client sets <code>Content-Type: application/json</code>

    .

    ```bash theme={null}
    curl -s \
      -H 'Authorization: Bearer <SESSION_TOKEN>' \
      -H 'Content-Type: application/json' \
      -d '{}' \
      https://dev-api.machines.cash/partner/v1/cards/secrets/session
    ```
  </Step>

  <Step title="Get card secrets (optional)">
    <b>Endpoint</b>

    : <a href="/api/cards/secrets" target="_blank" rel="noreferrer"><code>POST /cards/{"{cardId}"}/secrets</code></a>

    \
    <b>Body</b>

    : <code>{"{ sessionId }"}</code>

    (from the secrets session helper)
  </Step>
</Steps>

## Fields (create/update)

<ParamField path="encryptedName" type="object">
  Optional encrypted card label field <code>{"{ v, iv, ct }"}</code>

  . Generate with <a href="/api/encryption/encrypt" target="_blank" rel="noreferrer"><code>POST /encryption/encrypt</code></a>

  .
</ParamField>

<ParamField path="limit.amountCents" type="integer">
  Spending cap in cents.
</ParamField>

<ParamField path="limit.frequency" type="string">
  One of: <code>perAuthorization</code>

  , <code>per24HourPeriod</code>

  , <code>per7DayPeriod</code>

  , <code>per30DayPeriod</code>

  , <code>perYearPeriod</code>

  , <code>allTime</code>

  .
</ParamField>

## Response (secrets session)

<ResponseField name="sessionId" type="string" required>
  Session id used to fetch encrypted PAN/CVC.
</ResponseField>

<ResponseField name="secretKey" type="string" required>
  16‑byte secret (hex) used to decrypt PAN/CVC with AES‑128‑GCM.
</ResponseField>

## Response (secrets)

<ResponseField name="encryptedPan.data" type="string" required>
  Base64 ciphertext + auth tag.
</ResponseField>

<ResponseField name="encryptedPan.iv" type="string" required>
  Base64 IV.
</ResponseField>

<ResponseField name="encryptedCvc.data" type="string" required>
  Base64 ciphertext + auth tag.
</ResponseField>

<ResponseField name="encryptedCvc.iv" type="string" required>
  Base64 IV.
</ResponseField>

<ResponseField name="expirationMonth" type="number" required>
  Expiration month (MM).
</ResponseField>

<ResponseField name="expirationYear" type="number" required>
  Expiration year (YYYY).
</ResponseField>

<ResponseField name="last4" type="string" required>
  Last 4 digits.
</ResponseField>

## Card labels vs card secrets

* Card labels use <code>/encryption/encrypt</code>

  and <code>/encryption/decrypt</code>

  .
* Card secrets (PAN/CVC) use <code>/cards/secrets/session</code>

  * <code>/cards/{"{cardId}"}/secrets</code>

  .
* Decrypt card labels on your backend and send plaintext labels to your frontend.
* Card labels are optional, but recommended for clean UI.

## Card limits

* amountCents: integer amount in cents (e.g., 5000 = \$50). Minimum 1.
* frequency: one of
  * <code>perAuthorization</code>

    — max per single authorization
  * <code>per24HourPeriod</code>

    — rolling 24‑hour spend cap
  * <code>per7DayPeriod</code>

    — rolling 7‑day spend cap
  * <code>per30DayPeriod</code>

    — rolling 30‑day spend cap
  * <code>perYearPeriod</code>

    — rolling 1‑year cap
  * <code>allTime</code>

    — lifetime cap

Examples

```json theme={null}
{ "limit": { "amountCents": 5000, "frequency": "perAuthorization" } }
{ "limit": { "amountCents": 20000, "frequency": "per24HourPeriod" } }
```

To change a limit, PATCH the card with a new limit object. To remove a limit, set a permissive value (for example a very high allTime cap) or contact us if you need a true “no limit” configuration for your program.

## Lock / unlock / update limits

* <code>PATCH /cards/{"{cardId}"}</code>

  with <code>status: "locked"</code>

  to pause spend.
* Set <code>status: "active"</code>

  to unlock.
* Update limits by sending a new <code>limit</code>

  payload.

## Delete

<code>DELETE /cards/{"{cardId}"}</code>

cancels immediately.

<a id="secrets-sessionid" />

## Card number secrets (PAN/CVC)

This flow is only for retrieving the card number (PAN) and CVC. Do not use it for card labels.

1. Call <code>POST /cards/secrets/session</code>

   to get <code>sessionId</code>

   and <code>secretKey</code>

   .
2. Call <code>POST /cards/{"{cardId}"}/secrets</code>

   with <code>{"{ sessionId }"}</code>

   .
3. Decrypt <code>encryptedPan</code>

   and <code>encryptedCvc</code>

   locally using AES‑128‑GCM with the <code>secretKey</code>

   .

<Note>
  This endpoint requires the <code>cards.secrets.read</code>

  scope.
</Note>

<Note>
  <code>/encryption/decrypt</code>

  is for card labels only. Use <code>/cards/{"{cardId}"}/secrets</code>

  for PAN/CVC.
</Note>

<Note>
  The <code>sessionId</code>

  used here is different from your API session token. Always request it from <code>/cards/secrets/session</code>

  .
</Note>

<Note>
  No decrypted PAN/CVC ever leaves your process; only encrypted blobs are returned by the API.
</Note>
