Cards API

Cards are the content units pushed to channels. Each card contains an ordered array of blocks.

Create Card

POST /api/v1/channels/{channelId}/cards

Creates a new card in the channel. Counts toward the 200 cards/day limit.

Request Body

Field Type Required Description
blocks Block[] Yes Array of block objects (see Blocks)
status string No Card status: "default", "success", "warning", "error", "pending"

Example

curl -X POST /api/v1/channels/3f7a1b2c-.../cards \
  -H "Authorization: Bearer ofd_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "success",
    "blocks": [
      {
        "type": "text",
        "content": "Order #1234 processed",
        "size": "lg",
        "bold": true
      },
      {
        "type": "badge",
        "label": "Completed",
        "variant": "success"
      },
      {
        "type": "kv",
        "rows": [
          { "key": "Customer", "value": "Jane Smith" },
          { "key": "Total", "value": "$89.99" },
          { "key": "Items", "value": "3" }
        ]
      },
      {
        "type": "button",
        "buttons": [
          { "id": "view", "label": "View Order", "style": "primary" },
          { "id": "refund", "label": "Refund", "style": "danger" }
        ]
      }
    ]
  }'

Response `201 Created`

{
  "id": "7c8d9e0f-...",
  "channel_id": "3f7a1b2c-...",
  "created_at": "2025-01-15T10:30:00Z"
}

Block IDs

Blocks can optionally include an id field. If omitted, a UUID is auto-generated. Block IDs are used when patching specific blocks later.


Update Card

PATCH /api/v1/channels/{channelId}/cards/{cardId}

Updates a card's status and/or patches specific blocks. Only blocks listed in the blocks array are modified; others remain unchanged.

Request Body

Field Type Required Description
status string No New card status
blocks PatchBlock[] No Array of block patch objects

Block Patch Object

Each item in blocks specifies which block to update and what to change:

{
  "id": "block-uuid",
  "patch": { ...fields to update... }
}

The patch object contains only the fields you want to change within that block.

Patching a Text Block

curl -X PATCH /api/v1/channels/3f7a1b2c-.../cards/7c8d9e0f-... \
  -H "Authorization: Bearer ofd_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "blocks": [
      {
        "id": "text-block-id",
        "patch": {
          "content": "Order #1234 shipped!"
        }
      }
    ]
  }'

Patching a Badge Block

{
  "blocks": [
    {
      "id": "badge-block-id",
      "patch": {
        "label": "Shipped",
        "variant": "success"
      }
    }
  ]
}

Patching KV Rows

KV blocks support an append_rows field to add new rows without overwriting existing ones:

{
  "blocks": [
    {
      "id": "kv-block-id",
      "patch": {
        "append_rows": [
          { "key": "Tracking", "value": "1Z999AA1..." }
        ]
      }
    }
  ]
}

You can also overwrite all rows:

{
  "patch": {
    "rows": [
      { "key": "Status", "value": "Delivered" }
    ]
  }
}

Patching Individual Buttons

Button blocks support patching individual buttons by their id:

{
  "blocks": [
    {
      "id": "button-block-id",
      "patch": {
        "buttons": [
          {
            "id": "refund-btn",
            "patch": {
              "label": "Refunded",
              "disabled": true,
              "style": "secondary"
            }
          }
        ]
      }
    }
  ]
}

Updating Card Status

{
  "status": "success"
}

Full Update Example

curl -X PATCH /api/v1/channels/3f7a1b2c-.../cards/7c8d9e0f-... \
  -H "Authorization: Bearer ofd_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "success",
    "blocks": [
      {
        "id": "badge-id",
        "patch": { "label": "Delivered", "variant": "success" }
      },
      {
        "id": "btn-block-id",
        "patch": {
          "buttons": [
            { "id": "track-btn", "patch": { "disabled": true } }
          ]
        }
      }
    ]
  }'

Response `200 OK`

{
  "id": "7c8d9e0f-...",
  "channel_id": "3f7a1b2c-...",
  "status": "success",
  "blocks": [...],
  "updated_at": "2025-01-15T11:00:00Z"
}

Delete Card

DELETE /api/v1/channels/{channelId}/cards/{cardId}

Permanently deletes a card. Associated interactions will have their card_id set to null.

Response `204 No Content`

No response body.


Card Status Reference

The status field controls the visual border/highlight color of the card:

Value Color Use case
"default" Neutral Normal content
"success" Green Completed, approved, done
"warning" Yellow Needs attention, degraded
"error" Red Failed, rejected, critical
"pending" Blue/Grey In progress, waiting

Realtime Updates

Card changes are pushed to subscribers via Supabase Realtime. Any browser viewing /c/{channelId} will automatically receive:

  • New cards (inserts)
  • Updated cards (updates via PATCH)
  • Deleted cards (deletes)

No polling required — changes appear instantly in the UI.