Skip to main content
Customer Credits is in Experimental preview.

How transactions work

Every time you add or remove credits, a transaction is created. Transactions are permanent — you always have a complete history of what happened and why.

Credit

Add credits to an account

Debit

Remove credits from an account

Reverse

Undo a previous transaction

Credit — add credits

Use this when a customer earns credits, buys a credit pack, or receives a reward.
curl -X POST https://api.creem.io/v1/customer-credits/accounts/{account_id}/credit \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "500",
    "reference": "order_789",
    "idempotency_key": "reward_order_789"
  }'
{
  "id": "cct_3mNpK8rW2xY",
  "store_id": "store_xxx",
  "reference": "order_789",
  "idempotency_key": "reward_order_789",
  "reversal_of": null,
  "entries": [
    {
      "id": "cce_2hJnR6wP5bC",
      "transaction_id": "cct_3mNpK8rW2xY",
      "account_id": "cca_7kXmR2pQ9vN",
      "side": "credit",
      "amount": "500",
      "created_at": "2026-04-14T14:30:00.000Z"
    }
  ],
  "created_at": "2026-04-14T14:30:00.000Z"
}

Parameters

ParameterTypeRequiredDescription
amountstringHow many credits to add. String to support large numbers
referencestringLink this to your system — an order ID, campaign name, anything
idempotency_keystringPrevents double-processing on retries

Debit — remove credits

Use this when a customer spends credits, uses a feature, or redeems a reward.
curl -X POST https://api.creem.io/v1/customer-credits/accounts/{account_id}/debit \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "200",
    "reference": "checkout_456",
    "idempotency_key": "redeem_checkout_456"
  }'
Same parameters as credit. The response looks identical, just with "side": "debit" in the entry.
The API prevents negative balances — if a debit would bring the balance below zero, it returns an insufficient_balance error. Check the balance first if you want to show your users a friendly message.

Reverse — undo a transaction

Made a mistake? Order cancelled? Reverse a transaction to undo it. The original transaction stays in the history — a new opposite transaction is created so you always have a complete paper trail.
curl -X POST https://api.creem.io/v1/customer-credits/accounts/{account_id}/reverse \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_id": "cct_3mNpK8rW2xY"
  }'
The response includes "reversal_of": "cct_3mNpK8rW2xY" linking back to the original.
Reversals are idempotent — reversing the same transaction twice returns the original reversal.

Viewing history

See every credit and debit on an account, newest first.
curl "https://api.creem.io/v1/customer-credits/accounts/{account_id}/entries?limit=50" \
  -H "x-api-key: YOUR_API_KEY"
{
  "object": "list",
  "data": [
    {
      "id": "cce_8dFmQ1tY4wK",
      "transaction_id": "cct_5pRsL9uZ3cB",
      "account_id": "cca_7kXmR2pQ9vN",
      "side": "debit",
      "amount": "200",
      "created_at": "2026-04-14T15:00:00.000Z"
    },
    {
      "id": "cce_2hJnR6wP5bC",
      "transaction_id": "cct_3mNpK8rW2xY",
      "account_id": "cca_7kXmR2pQ9vN",
      "side": "credit",
      "amount": "500",
      "created_at": "2026-04-14T14:30:00.000Z"
    }
  ],
  "has_more": false
}
Each entry shows:
  • side"credit" (added) or "debit" (removed)
  • amount — how many credits
  • transaction_id — links back to the transaction (which has the reference and idempotency_key)

What is an idempotency_key?

An idempotency_key is a unique string you include with every credit or debit request. It’s your safety net against accidental duplicates. Imagine your app credits a customer 500 points for an order. The request goes through, but your app doesn’t get the response back (network hiccup, timeout, server restart). Without protection, retrying would give the customer 1,000 points instead of 500. The idempotency_key prevents this. When you retry with the same key, Creem recognizes it’s the same request and returns the original result — no double-crediting.
Use a key that’s tied to the business event, like reward_order_789 or topup_sub_123_2026-04. This way, even if your code accidentally fires twice for the same order, the customer only gets credited once.

How it works

ScenarioResult
First requestProcesses normally
Retry with same key + same bodyReturns original result, X-Idempotent-Replay: true header
Same key but different body409 Conflict error

Next steps

Accounts

Create, freeze, and manage accounts.

Recipes

Step-by-step guides for common patterns.

API Reference

Full endpoint schemas.

Introduction

Back to overview.