Public Alpha. Easel is in early development, so expect rough edges.

Easel

← API Documentation

Gift Cards API

Issue and manage your store's gift cards. A gift card is store credit a
buyer spends at checkout. Cards are either bought, as a product whose
delivery is gift_card (see Products), or
issued by you, such as to make up for a late parcel.

Endpoints

How Gift Cards Work

  • Codes are secret. A code is 28 characters from Crockford's base32
    alphabet, shown in groups of four (7K2M-…-QX4P), and holds 140 random
    bits. Easel keeps only its SHA-256 hash, so a code is returned exactly once:
    in the response that issues the card, or in the email to its recipient.
    last4 tells cards apart.
  • Currency. A card's balance is in the store's currency when it was
    issued, and it only pays at checkouts in that currency.
  • Checkout. A buyer enters a code at checkout. Checkout holds as much of
    the balance as the order costs, for as long as its payment can be made, so
    two checkouts can't spend the same balance. The buyer's card is charged
    only the rest. A card that pays the whole order needs no card payment at
    all. Paying turns the hold into a redeemed transaction in the same
    database transaction that records the order.
  • Gift cards bought. Each unit of a gift_card product creates a card
    worth the price paid for it once the order is paid. It is emailed to the
    recipient the buyer named in the cart, with their message, or to the buyer.
    Discount codes don't apply to gift cards, and they have no stock.
  • Tax. A gift card is a way to pay, not a discount. Tax is quoted on
    the whole order, and the card pays as much of the total, tax included, as
    its balance allows. Buying a gift card isn't taxed: tax is due on what the
    card buys when it's spent, so gift card lines are left out of the
    order's taxes.
  • Refunds. A refund of an order goes back to the buyer's card first, up
    to what was charged to it, and the rest back onto the gift card that paid
    for the order. See Refunds.
    A refund's tax is its share of the order's tax whichever way the money
    goes back.
  • Expiry. Cards never expire unless you set expires_at. Many places
    limit or forbid gift cards that expire.

List Gift Cards

Retrieve the store's gift cards, newest first.

Endpoint: GET /api/v1/gift-cards/

Permission Required: Read

Query Parameters

Parameter Type Description
status string Only cards with this status: active, used, expired, or disabled
after string Cursor for pagination. Gift card ID to return cards after
limit integer Number of cards to return (default 10, max 100)

The response reports has_more, which is true when another page follows.
An unknown status, a malformed after, or an invalid limit returns
INVALID_REQUEST_ERROR.

Request

curl -X GET "https://studio.easel.engineering/api/v1/gift-cards/?status=active&limit=20" \
  -H "Authorization: Bearer your_api_key_here"

Response

Status: 200 OK

{
  "data": [
    {
      "id": "gcd_d0b6fmv28q6vn14peun0",
      "last4": "QX4P",
      "currency": "USD",
      "initial_value": 5000,
      "balance": 3500,
      "status": "active",
      "recipient_email": "friend@example.com",
      "message": "Happy birthday!",
      "note": null,
      "expires_at": null,
      "disabled_at": null,
      "created_at": "2026-10-19T10:00:00Z",
      "updated_at": "2026-10-19T12:00:00Z"
    }
  ],
  "has_more": false
}

Issue Gift Card

Issue a gift card in the store's currency. The response is the only time
the code is returned.

Endpoint: POST /api/v1/gift-cards/

Permission Required: Write

Request Body

{
  "value": 2500,
  "recipient_email": "friend@example.com",
  "message": "Sorry your parcel was late.",
  "note": "Order #1042 arrived a week late"
}
Field Type Required Description
value integer Yes Value in the store's smallest currency unit, from 1 to 10000000
site_id string No Site whose name and address the card's email carries; defaults to the store's first site
recipient_email string No When set, the code is emailed to this address
message string No Message to the recipient, up to 500 characters; only kept with a recipient_email
note string No Your own note, never shown to the buyer, up to 500 characters
expires_at string No RFC 3339 time the card stops working; must be in the future

Request

curl -X POST "https://studio.easel.engineering/api/v1/gift-cards/" \
  -H "Authorization: Bearer your_api_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-12345" \
  -d '{"value": 2500, "recipient_email": "friend@example.com"}'

Response

Status: 201 Created

The gift card object with its code:

{
  "id": "gcd_d0b6fmv28q6vn14peun0",
  "last4": "QX4P",
  "currency": "USD",
  "initial_value": 2500,
  "balance": 2500,
  "status": "active",
  "recipient_email": "friend@example.com",
  "message": null,
  "note": null,
  "expires_at": null,
  "disabled_at": null,
  "created_at": "2026-10-19T10:00:00Z",
  "updated_at": "2026-10-19T10:00:00Z",
  "code": "7K2M-A9QD-0FZT-3HWB-P6NR-K1XV-QX4P"
}

Error Responses

Invalid value, email, expiry, or text

Status: 400 Bad Request

{
  "error": "value must be between 1 and 10000000",
  "code": "INVALID_FIELD"
}

Get Gift Card

Endpoint: GET /api/v1/gift-cards/{gift_card_id}/

Permission Required: Read

curl -X GET "https://studio.easel.engineering/api/v1/gift-cards/gcd_d0b6fmv28q6vn14peun0/" \
  -H "Authorization: Bearer your_api_key_here"

Status: 200 OK with the gift card object, or
404 Not Found.


Update Gift Card

Replace a card's expiry and note. A null or absent value clears it.

Endpoint: PUT /api/v1/gift-cards/{gift_card_id}/

Permission Required: Write

{
  "expires_at": "2027-12-31T23:59:59Z",
  "note": "Goodwill credit"
}
Field Type Required Description
expires_at string|null No RFC 3339 time the card stops working; a new expiry must be in the future
note string|null No Your own note, up to 500 characters

Status: 200 OK with the updated gift card object.


Adjust Balance

Raise a card's balance by a positive amount or lower it by a negative one.
The change is added to the card's history with your note.

Endpoint: POST /api/v1/gift-cards/{gift_card_id}/adjustments/

Permission Required: Write

{
  "amount": -500,
  "note": "Spent in the shop"
}
Field Type Required Description
amount integer Yes Change in the store's smallest currency unit; not zero
note string No Why, up to 500 characters

Status: 200 OK with the updated gift card object.

The balance can't go below zero, below what open checkouts hold of it, or
above 10000000; such a change returns 400 Bad Request with
INVALID_FIELD.


Disable and Enable

A disabled card can't be applied at checkout until you enable it again. Its
balance is kept. A checkout that already holds part of the card may still
spend that part, since its buyer may already have paid the rest. Disabling
a disabled card, or enabling an enabled one, changes nothing.

Endpoints:
POST /api/v1/gift-cards/{gift_card_id}/disable/ and
POST /api/v1/gift-cards/{gift_card_id}/enable/

Permission Required: Write

Status: 200 OK with the updated gift card object.


List Transactions

A card's history, newest first. Entries are only ever added: every change to
the balance or status has one.

Endpoint: GET /api/v1/gift-cards/{gift_card_id}/transactions/

Permission Required: Read

Parameter Type Description
after string Cursor. Transaction ID to return older entries after
limit integer Number of entries to return (default 10, max 100)
{
  "data": [
    {
      "id": "gct_d0b6fmv28q6vn14peun1",
      "type": "redeemed",
      "amount": -1500,
      "balance": 3500,
      "order_id": "ord_d0b6fmv28q6vn14peun0",
      "note": null,
      "actor": {"type": "customer", "name": null},
      "created_at": "2026-10-19T12:00:00Z"
    },
    {
      "id": "gct_d0b6fmv28q6vn14peun0",
      "type": "issued",
      "amount": 5000,
      "balance": 5000,
      "order_id": "ord_d0b6fmv28q6vn14peuaa",
      "note": null,
      "actor": {"type": "system", "name": null},
      "created_at": "2026-10-19T10:00:00Z"
    }
  ],
  "has_more": false
}

Transaction Types

  • issued - The card was made with its initial balance
  • redeemed - Balance spent on an order (negative amount)
  • refunded - Balance put back by a refund of an order
  • adjusted - You raised or lowered the balance
  • disabled, enabled - You disabled or enabled the card (amount is 0)

The actor is who made the change, as in an
order's history.


Gift Card Object

Field Type Description
id string Gift card public ID
last4 string Last four characters of the code
currency string ISO 4217 currency of the balance
initial_value integer Value when issued
balance integer What's left to spend
status string active, used (no balance left), expired, or disabled, judged when read
recipient_email string|null Who the card was emailed to
message string|null The buyer's message to the recipient
note string|null Your note
expires_at string|null When the card stops working, or null for never
disabled_at string|null When the card was disabled
created_at string ISO 8601 timestamp
updated_at string ISO 8601 timestamp