Billing & FinOps

Preview — pending review

This reference is generated from the platform API contract and is still under review. Operations, fields, and descriptions can change before publication.

Redeem a coupon code into an active credit grant

POST
/scopes/{scopeId}/billing/credits/actions/redeem

Redeems a coupon code against the caller's tenant ("Redeem" in the Redeem-a-coupon panel of the Credits page). The submitted code is normalized (trimmed, upper-cased) and validated against the tenant's redeemable-code table; a valid code materializes a fresh active credit grant with source: coupon, consumed: 0, remaining equal to the granted amount (in ten-thousandths of the currency unit), grantedAt set to now and expiresAt derived from the code's validity window. Redeemed credits apply automatically to the next invoice. The grant is resolved by the body's code ALONE — there is no {creditId} path parameter. A customer knows a coupon's code, never its internal credit id, so requiring the id would demand information the customer cannot have; a coupon code is unique per tenant, so it is sufficient on its own to address the grant. Validation: the normalized code must exist in the tenant's redeemable-code table, not be already consumed and not be expired. Every one of these failures (unknown, already redeemed, expired) returns the SAME 422 VALIDATION_FAILED on field: code with the same body, so a caller cannot tell which codes exist; caller must be authorized for billing commands (otherwise 403 FORBIDDEN). None of these is a 404. Rate limit & audit: every attempt is recorded (outcome, caller, scope and a hash of the code — never the code itself). After 5 failed attempts by the tenant within 15 minutes, redeem answers 429 RATE_LIMITED with details.retryAfterSeconds until the oldest failure leaves the window. Async & state: Synchronous; returns 200 with the resulting credit grant in active state. A resource.updated SSE frame (kind: credit, patch: {status, remaining, grantedAt}) is emitted so open credit lists refresh; the resulting state is immediately available to subsequent reads. Errors: 401 unauthenticated; 403 caller lacks billing command permission; 404 unknown/unauthorized scope; 422 unknown, already redeemed or expired coupon code, or missing code field; 429 too many failed attempts; 500 on backend failure. Idempotency/Concurrency: This operation does not use Idempotency-Key; it may be omitted and a sent one is ignored. A retry is processed again rather than answered from a stored result. A coupon is single-use: the first successful redeem stamps it redeemed under a FOR UPDATE row lock, and any later redeem of the same code (including a retry of a request that already succeeded) is refused with the same 422 VALIDATION_FAILED on field: code as an unknown code and counts as a failed attempt toward the 429 limit. The credit is never granted twice.

Authorization

bearerToken
headerAuthorizationBearer <token>

An API token (pc_live_…) or a service-account key (sak_live_…), created in Identity & Access Management and sent as Authorization: Bearer <token>. Requests are rate limited per credential and per tenant: every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request gets 429 RATE_LIMITED with Retry-After.

Path Parameters

scopeId*string

Opaque ownership+authorization scope resolving to tenant + subscription + project.

Request Body

application/json
  1. body

Coupon redemption payload; the code is normalized (trimmed, upper-cased) before validation.

code*string

Coupon code to redeem against the tenant.

Response Body

Coupon accepted; the resulting active credit grant.

application/json
  1. response

A credit grant (coupon, promotion, support credit or prepaid top-up) with balances in ten-thousandths of the currency unit.

id*string
source*CreditSource

Origin of a credit grant.

Value in"coupon""promo""support-credit""prepaid"
label*string
code*|

Coupon code for coupon-sourced credits, otherwise null.

granted*integer

Granted amount in ten-thousandths of the currency unit.

consumed*integer

Consumed amount in ten-thousandths of the currency unit.

remaining*integer

Remaining amount in ten-thousandths of the currency unit (0 for exhausted or expired grants).

grantedAt*string
Formatdate-time
expiresAt*string
Formatdate-time
status*CreditStatus

Credit grant status.

Value in"active""exhausted""expired"
reference*string

ARN-style billing reference for the credit grant.

curl -X POST "https://example.com/scopes/string/billing/credits/actions/redeem" \  -H "Content-Type: application/json" \  -d '{    "code": "PUBLICCLOUD-WELCOME-300"  }'
{  "id": "cr-prepaid-apr",  "source": "coupon",  "label": "Prepaid top-up — wire transfer",  "code": "WELCOME2026",  "granted": 0,  "consumed": 0,  "remaining": 0,  "grantedAt": "2019-08-24T14:15:22Z",  "expiresAt": "2019-08-24T14:15:22Z",  "status": "active",  "reference": "arn:publiccloud:billing:ist-1:acct-1:credit/cr-prepaid-apr"}