> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getmint.money/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getmint.money/_mcp/server.

# Backend Payment Creation

> Mint payments should always be created server-side with the Mint secret key.

Mint payments must be created on your backend, never in the browser. Your
secret key identifies your organization and can create payments, so treat it
like any other server-side credential.

## Before you start

You need a checkout ID and a secret API key from the Mint Dashboard. Use a test
checkout and a test key while integrating.

## Create a payment

Send a `POST` request to `https://api.getmint.money/v1/payments` with your
secret key in `x-api-key`.

```bash
curl https://api.getmint.money/v1/payments \
  --request POST \
  --header 'content-type: application/json' \
  --header 'x-api-key: sk_test_your_secret_key' \
  --data '{
    "checkout_id": "your_checkout_id",
    "amount": 49.99,
    "currency": "USD",
    "order_id": "order_1234",
    "customer_id": "customer_456",
    "return_url": "https://example.com/orders/order_1234",
    "metadata": { "source": "web" }
  }'
```

Mint returns the payment in `data`. Persist `data.id` alongside your order. If
you use hosted payments, redirect the buyer to `data.payment_url`.

```json
{
  "data": {
    "id": "payment_id",
    "status": "pending",
    "payment_url": "https://pay.getmint.money/..."
  }
}
```

The full request and response fields are available in the API Reference.

For customer integrations, use the production Mint API base URL and a test
checkout when validating the flow.

## Practical guidance

* Validate amount and currency before calling Mint.
* Keep your secret key in server-side environment variables only.
* Attach your own order and customer references at payment creation time.
* Persist the Mint payment ID in your own system for reconciliation.
* Make your own order-creation flow idempotent so a browser retry does not
  create two orders.
* Do not mark an order paid from the creation response or a browser redirect;
  use a verified `payment.paid` webhook instead.