---
title: "Redeem a credit code"
method: POST
path: "/credits/redeem"
tags: ["Credits"]
---

# Redeem a credit code

`POST /credits/redeem`

## Request

- Base URL: `https://api.primitive.dev/v1`
- URL: `https://api.primitive.dev/v1/credits/redeem`
- Auth: HTTP bearer

Redeem a credit code for the authenticated organization. The credit is added to the organization prepaid credit and shows in `GET /credits/balance` under `prepaid_credit`. Redeeming requires an organization owner or admin: an API key redeems with the authority of the user who created it (or the member it was transferred to), based on that user's current role, and a key without that authority gets the same `credit_code_invalid` refusal as an unknown code. A key transferred to another member without being rotated is refused with `403` and `error.details.reason` `key_transferred_unrotated`: rotate it and redeem with its successor. The `Idempotency-Key` header is required. Retrying with the same key and code returns the original grant with `replayed: true` and grants nothing new; the same key with a different code is refused with `idempotency_key_reused`. Every refusal carries a human-readable `error.message` that can be shown to the user as is.

## Headers

- `Idempotency-Key` string, required

## Request body

- RedeemCreditCodeInput
  - `code` string, required: The credit code to redeem. Surrounding whitespace is ignored; the rest must be 1 to 256 characters.

## Response `200`

The code was redeemed, or this request replayed an earlier redemption with the same Idempotency-Key.

- object
  - `success` true, required
  - `data` CreditRedemption, required
    - `redemption_id` string, required: Identifier of the redemption.
    - `amount_micros` string, required: Credit granted, in micros of `currency` (1 USD = 1000000 micros).
    - `currency` string, required: Currency of the granted credit, for example `usd`.
    - `granted_at` string, date-time, required: When the credit was granted.
    - `expires_at` string, date-time, nullable, required: When the granted credit expires, or null when it does not expire.
    - `label` string, nullable, required: Customer-facing label of the promotion, when it has one.
    - `replayed` boolean, required: True when this Idempotency-Key already redeemed this code and the original grant is returned. No second grant is made.
    - `message` string, required: Human-readable summary of the grant, suitable to show as is.

## Other responses

- `400`: `idempotency_key_required` means the Idempotency-Key header is missing. `validation_error` means the header is empty, longer than 200 characters or not printable non-space ASCII, or the body is invalid. `error.code` is one of: `idempotency_key_required`, `validation_error`.
- `401`: Invalid or missing API key
- `403`: Authenticated caller lacks permission for the operation
- `409`: The organization or user already redeemed this code, or already redeemed another code in the same exclusive group (a set of codes of which each organization or user may redeem only one). `error.code` is one of: `credit_code_already_redeemed`.
- `422`: The code cannot be redeemed. `credit_code_invalid` covers unknown, expired and exhausted codes and callers without authority to redeem; `credit_code_not_eligible` means the organization does not meet the promotion terms; `credit_code_balance_cap` means the organization already holds the most promotional credit it can; `idempotency_key_reused` means this Idempotency-Key already redeemed a different code. `error.code` is one of: `credit_code_invalid`, `credit_code_not_eligible`, `credit_code_balance_cap`, `idempotency_key_reused`.
- `429`: Too many requests or redemption attempts. Wait for `Retry-After` when present. `error.code` is one of: `rate_limited`.
- `503`: The code could not be redeemed right now. Retry later with the same Idempotency-Key. `error.code` is one of: `service_unavailable`.

## Changes

> 32 revisions in range; 1 not diffed.

- **2026-11-03** `bce409c97acb`: 217 warning
  - added the new `access_mode_unavailable` enum value to the `error/code` response property for the response status `400`
  - added the new `access_mode_unavailable` enum value to the `error/code` response property for the response status `401`
  - added the new `access_mode_unavailable` enum value to the `error/code` response property for the response status `403`
  - added the new `access_mode_unavailable` enum value to the `error/code` response property for the response status `409`
  - …213 more
  - …this revision’s changelog is incomplete
- **2026-10-21** `0360ea8d4f3d`: 91 warning
  - added the new `agent_changed` enum value to the `error/code` response property for the response status `400`
  - added the new `agent_changed` enum value to the `error/code` response property for the response status `401`
  - added the new `agent_changed` enum value to the `error/code` response property for the response status `403`
  - added the new `agent_changed` enum value to the `error/code` response property for the response status `409`
  - …87 more
- …earlier changes not shown

[Operation history](https://skmtc.dev/primitive/apis/primitive-api/changes/credits/redeem/post.md)

---

[API](https://skmtc.dev/primitive/apis/primitive-api.md) - [All operations](https://skmtc.dev/primitive/apis/primitive-api/llms.txt) - [OpenAPI document](https://skmtc.dev/primitive/apis/primitive-api/revisions/bce409c97acb?raw)
