Sample API Documentation
Payments API (v1)
This is a realistic API documentation sample for a payment-processing service. It demonstrates authentication, idempotency, pagination, request/response examples, and an error model.
Base URL
https://api.acmepayments.example/v1
Authentication
Authenticate using an API key sent in the Authorization header.
Authorization: Bearer <API_KEY>
Keep keys server-side. If a key is leaked, rotate it immediately.
Idempotency
For requests that create or modify resources (for example, POST /payments), send an idempotency key to prevent
accidental duplicate charges if a client retries.
Idempotency-Key: 2a9f9f03-18c4-4e2a-a4b7-3a91b1b7d8c1
The server stores the first successful response for that key for 24 hours. Retries return the same response.
Common Headers
Content-Type: application/json
Accept: application/json
Authorization: Bearer <API_KEY>
Idempotency-Key: <UUID> (recommended for POST/PATCH)
Resource Model
Payment
- id (string): Payment identifier, for example
pay_3Xn9... - amount (integer): Amount in minor units (cents), for example
1999 - currency (string): ISO 4217 currency code, for example
USD - status (string):
requires_confirmation|succeeded|failed|refunded - customer_id (string): Customer identifier
- created_at (string): RFC 3339 timestamp
- metadata (object): Optional key/value data (max 20 keys)
Endpoints
1) Create a payment
POST /payments
Request body
{
"amount": 1999,
"currency": "USD",
"customer_id": "cus_8F3k1",
"payment_method": {
"type": "card",
"card_token": "tok_visa_123"
},
"confirm": true,
"metadata": {
"order_id": "A-100045"
}
}
Notes
amountis in minor units (cents for USD).confirm=trueattempts to capture immediately. If omitted, the payment is created inrequires_confirmation.
Response: 201 Created
{
"id": "pay_3Xn9Qv0c",
"amount": 1999,
"currency": "USD",
"status": "succeeded",
"customer_id": "cus_8F3k1",
"created_at": "2026-01-10T12:00:00Z",
"metadata": {
"order_id": "A-100045"
}
}
2) Retrieve a payment
GET /payments/{payment_id}
GET /payments/pay_3Xn9Qv0c
Response: 200 OK
{
"id": "pay_3Xn9Qv0c",
"amount": 1999,
"currency": "USD",
"status": "succeeded",
"customer_id": "cus_8F3k1",
"created_at": "2026-01-10T12:00:00Z",
"metadata": {
"order_id": "A-100045"
}
}
3) List payments (pagination)
GET /payments?limit=20&starting_after=pay_...
Parameters
- limit (integer, 1–100): Number of results to return (default 20)
- starting_after (string): Cursor for pagination (exclusive)
- customer_id (string): Optional filter
Response: 200 OK
{
"data": [
{
"id": "pay_3Xn9Qv0c",
"amount": 1999,
"currency": "USD",
"status": "succeeded",
"customer_id": "cus_8F3k1",
"created_at": "2026-01-10T12:00:00Z",
"metadata": {"order_id": "A-100045"}
}
],
"has_more": false,
"next_cursor": null
}
4) Refund a payment
POST /payments/{payment_id}/refunds
Request body
{
"amount": 1999,
"reason": "requested_by_customer"
}
Response: 201 Created
{
"refund_id": "ref_72Kp1",
"payment_id": "pay_3Xn9Qv0c",
"amount": 1999,
"currency": "USD",
"status": "succeeded",
"created_at": "2026-01-10T12:05:00Z"
}
Error Handling
Errors return JSON with a stable shape. Use error.code for programmatic handling and show
error.message to users only after sanitization.
Error object
{
"error": {
"type": "invalid_request",
"code": "amount_too_small",
"message": "Amount must be at least 50 cents.",
"param": "amount",
"request_id": "req_9n2Z1"
}
}
Common HTTP status codes
- 400 Invalid request (missing fields, bad types)
- 401 Authentication failed (missing/invalid API key)
- 403 Not permitted (key lacks scope)
- 404 Resource not found
- 409 Conflict / idempotency mismatch
- 429 Rate limited
- 500 Server error
Rate limiting
The API enforces rate limits per key. When limited, responses include:
429 Too Many Requests
Retry-After: 2
Best Practices
- Always send Idempotency-Key for create/modify requests.
- Log request_id to correlate client-side errors with server logs/support.
- Validate currencies and minor-unit amounts on the client.
- Version your integrations by pinning to
/v1and monitoring changelogs.
This is a sample article to demonstrate how I write.