---
title: "Buy a tier with USDC (x402)"
method: POST
path: "/api/x402/submit"
tags: ["x402"]
---

# Buy a tier with USDC (x402)

`POST /api/x402/submit`

## Request

- Base URL: `https://curlship.com`
- URL: `https://curlship.com/api/x402/submit`
- Auth: none declared

`bronze_lifetime` is $30 USDC once — the listing is owned forever. `platinum` is $49 USDC for a prepaid year (renewals extend from the current expiry, never shorten it). Without `PAYMENT-SIGNATURE` the response is 402 + a `PAYMENT-REQUIRED` quote; send the signed payment and the tier is granted after on-chain settlement. Same URL/email/listing rules as POST /api/submit's paid path. Rate limit: 30 checkout requests/hour per IP.

## Headers

- `PAYMENT-SIGNATURE` string

## Request body

- object
  - `url` string, uri, required
  - `email` string, email, required
  - `tier` 'bronze_lifetime' | 'platinum', required

## Response `200`

Payment settled and granted. `PAYMENT-RESPONSE` (base64 JSON) carries the settlement receipt; `tx_hash` is also in the body.

- object
  - `ok` boolean
  - `tx_hash` string
  - `listing` object
    - `id` integer
    - `url` string, uri
    - `tier` 'free' | 'bronze' | 'silver' | 'gold' | 'platinum'
    - `title` string, nullable
    - `description` string, nullable
    - `image` string, uri, nullable
    - `has_badge` boolean: True if a dofollow link back to curlship.com was found on the site.
    - `created_at` string, date-time, nullable: When the listing was created, UTC.

## Other responses

- `202`: The payment was broadcast but is not confirmed yet. The tx hash rides `PAYMENT-RESPONSE` and `tx_hash` in the body — retry the same PAYMENT-SIGNATURE and the ledger reconciles it; nothing is granted until the payment confirms.
- `400`: Malformed input, or a PAYMENT-SIGNATURE that is not a readable x402 v2 exact-EVM payment (v1 envelopes and Permit2-shaped payloads are refused before any verification).
- `402`: Payment required — or the supplied payment could not be verified/settled (the reason is in `error`). `PAYMENT-REQUIRED` (base64 JSON, x402Version 2) and the body both carry `accepts[0]`: scheme `exact`, the configured network, the USDC asset, the atomic amount, `payTo`, `maxTimeoutSeconds` 300, and `extra` with the EIP-712 token name/version plus an HMAC quote binding. Echo `accepts[0]` back as `accepted` inside a signed PAYMENT-SIGNATURE to pay. A tampered quote re-402s with a fresh one.
- `409`: The payment settled but the grant hit a business conflict — booked refund-needed for a human to reconcile — or a replayed payment already reached a reconciled state.
- `429`: Rate limit exceeded. Retry-After is the wait in seconds. RateLimit-Policy names the window that was hit. RateLimit repeats that name with r=0 and t equal to Retry-After. Windows: submit 10 per 3600s, verify 30 per 3600s, checkout 30 per 3600s, edit 5 per 3600s per IP, edit-listing 3 per 86400s per listing.
- `503`: The x402 rail is enabled but not serving (misconfiguration or an unhealthy chain probe at startup) — it fails closed instead of minting quotes that could never settle.

---

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