---
title: "Start a credit top-up"
method: POST
path: "/credits/topups"
tags: ["Gateway"]
---

# Start a credit top-up

`POST /credits/topups`

## Request

- Base URL: `https://api.phaseo.app/v1`
- URL: `https://api.phaseo.app/v1/credits/topups`
- Auth: HTTP bearer

Asks to add credits to the authenticated workspace. Needs the opt-in billing:write scope and workspace membership. Nothing is charged here. With a saved card, every workspace owner and admin is emailed a single-use link and one of them confirms or declines the charge. Without one, the response has a checkout_url where an owner or admin pays with a new card, which is saved for later top-ups. Amounts are $5 to $500. A workspace can have 5 pending top-ups, and each expires after 30 minutes.

## Headers

- `Idempotency-Key` string

## Request body

- CreditTopupCreateRequest
  - `amount_usd` number, required: Amount in US dollars, with at most two decimal places.
  - `workspace_id` string, uuid: Optional. Must match the authenticated workspace.
  - `idempotency_key` string: Optional idempotency key. Repeating it returns the same top-up instead of creating another.

## Response `200`

Existing top-up for this idempotency key

- CreditTopupResponse
  - `ok` true, required
  - `topup` CreditTopup, required
    - `id` string, uuid, required
    - `workspace_id` string, uuid, required
    - `status` 'pending' | 'confirmed' | 'declined' | 'expired' | 'paid' | 'failed', required
    - `final` boolean, required: True once the status will not change (paid, declined, expired or failed). Stop polling then.
    - `reason` string, nullable, required: Reason code for declined, expired and failed top-ups, for example declined, expired, card_declined or authentication_failed.
    - `message` string, required: A sentence that explains what happens next.
    - `flow` 'checkout' | 'saved_card', required: checkout when an owner or admin pays with a new card at checkout_url; saved_card when an owner or admin confirms a charge to the saved card by email.
    - `amount_cents` integer, required
    - `amount_usd` number, required
    - `currency` string, required
    - `payment_method` object, nullable, required
      - `brand` string, nullable
      - `last4` string, nullable
    - `checkout_url` string, uri, nullable, required: Phaseo page where an owner or admin pays with a new card. Only in the response that created a pending checkout top-up.
    - `next_action` 'open_checkout_url' | 'await_email_confirmation' | 'await_payment' | 'null', nullable, required
    - `confirmation_recipients` integer: Number of owners and admins emailed to confirm a saved_card top-up.
    - `expires_at` string, date-time, required
    - `created_at` string, date-time, required
    - `decided_at` string, date-time, nullable, required
    - `paid_at` string, date-time, nullable, required

## Other responses

- `201`: Top-up created
- `400`: Invalid amount (invalid_amount, amount_below_minimum or amount_above_maximum)
- `401`: Unauthorized
- `403`: Forbidden
- `409`: Idempotency key reused for a different top-up, or no owner or admin can confirm it
- `429`: The workspace already has 5 pending top-ups
- `500`: Server error
- `503`: Card payments are not available

## Changes

- **2026-10-29** `bb50845101e4`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/phaseo/apis/phaseo-gateway-api/changes/credits/topups/post.md)

---

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