---
title: "Purchase Token Grants"
method: POST
path: "/api/v1/purchases/token-grants"
tags: ["User APIs", "purchases"]
---

# Purchase Token Grants

`POST /api/v1/purchases/token-grants`

Create a token purchase for the client with comprehensive validation and error handling.

This endpoint provides a production-ready token purchase flow supporting:
- Credit card payments via Stripe PaymentIntent
- ACH payments via Stripe PaymentIntent
- Invoice payments for eligible plans

The endpoint implements proper:
- Input validation and sanitization
- User permission checks
- Business rule enforcement
- Comprehensive error handling
- Audit logging

Args:
    request: Purchase request with token_amount, payment_method, and optional fields
    user: Authenticated user making the request
    token_purchase_service: Service handling the token purchase logic

Returns:
    Dict containing purchase details:
    - payment_method: The payment method used
    - payment_id: Internal payment tracking ID
    - token_amount: Number of tokens purchased
    - total_amount: Total cost in USD
    - For Card/ACH: PaymentIntent with client_secret for frontend processing
    - For Invoice: Invoice details with hosted_invoice_url

Raises:
    400: Invalid input parameters or business rule violations
    401: User not authenticated
    403: User lacks permission for this client, or the client is a
         wholesale client (their allowance comes from the contract tier)
    404: Client plan or tokens not found
    422: Business logic violations
    500: System errors
    502: External service (Stripe) errors

## Request body

- BuyTokensRequest
  - `token_amount` number, required
  - `payment_method` string, required
  - `is_recurring` boolean
  - `success_url` string, nullable
  - `cancel_url` string, nullable
  - `token_id` string, uuid, nullable — Optional token ID to use for purchase. If not provided, the primary active token will be used.
  - `token_purchase_type` 'primary' | 'mcp' | 'mcp_primary', nullable — Optional token purchase type. If 'mcp_primary' (or legacy 'mcp') is provided and token_id is not set, the backend will use the MCP Primary token id from environment configuration.

## Response `200`

Successful Response

- unknown

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/carbonarc/apis/carbon-arc-client-admin-api.md) · [All operations](https://skmtc.net/carbonarc/apis/carbon-arc-client-admin-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/carbonarc/carbon-arc-client-admin-api/revisions/a8ca30023371/schema)
