--- title: "Refunds" description: "Learn how to process refunds for completed payments through the Tokenz Refunds API." source: "https://docs.tokenz.one/en/v2/refunds" api_version: "v2" locale: "en" version_status: "current" docs_stage: "prod" --- # Refunds Learn how to process refunds for completed payments through the Tokenz Refunds API. The Refunds API allows you to return funds to customers for completed orders. You can initiate refunds, track refund status, and manage the refund lifecycle. **Amount format:** All monetary values (such as `amount` fields) are expressed in the smallest minor unit of each currency. See [Supported currencies](https://docs.tokenz.one/en/v2/checkout/currency) for the exact encoding per currency. ## Overview The refund system provides refund management capabilities: - **Refund Creation**: Initiate refunds for completed orders with specified reasons - **Status Tracking**: Monitor refund progress through pending or failed states - **Audit Trail**: Track who initiated refunds and when - **Test Mode**: Full test environment support for development and testing ## Refund lifecycle Refunds progress through a defined lifecycle: 1. **Refund Initiation**: Merchant or API initiates a refund for a completed order 2. **Processing**: Refund is processed asynchronously (status remains `pending`) 3. **Failure**: Refund may fail if there are issues (status changes to `failed`) ### Refund status values Refunds can have the following statuses: - `pending`: The refund has been initiated and is being processed - `failed`: The refund attempt failed ```mermaid sequenceDiagram; autonumber; participant M as Merchant App; participant T as Tokenz API; %% Refund Creation Flow; M->>T: POST /v2/refunds (Initiate Refund); T->>T: Validate order and amount; T-->>M: Return Refund (status: pending); T->>T: Process refund asynchronously; T->>M: Webhook notification (created/failed); ``` ## Creating a refund To initiate a refund, send a POST request to the refunds endpoint with the order ID and refund reason: ```bash curl --request POST \ --url https://api.tokenz.one/v2/refunds \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \ --data '{ "orderId": "order_1p4LPTRKB5Z", "reason": "customer_cancellation", "detail": "Customer requested cancellation" }' ``` ### Required parameters - `orderId`: The ID of the order to refund (must be a completed order) - `reason`: The reason for the refund. Valid values: - `customer_cancellation`: The customer cancelled the order - `duplicate_payment`: The payment was a duplicate - `other`: Other reason (requires `detail` field) - `detail`: Optional detailed explanation (required when reason is `other`) ### Response A successful refund creation returns a refund object: ```json { "refund": { "id": "refund_1p4LS47fB1h", "object": "refund", "orderId": "order_1p4LPTRKB5Z", "amount": { "amount": 10000, "currency": "JPY" }, "consumerAmount": { "amount": 10000, "currency": "JPY" }, "status": "pending", "reason": "customer_cancellation", "initiatedBy": "apikey", "test": false, "createdAt": "2024-10-07T10:30:00Z", "updatedAt": "2024-10-07T10:30:00Z" } } ``` ## Retrieving a refund Get the current status and details of a specific refund: ```bash curl --request GET \ --url https://api.tokenz.one/v2/refunds/refund_1p4LS47fB1h \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### Response fields - `id`: Unique identifier for the refund - `orderId`: The ID of the refunded order - `amount`: The refunded amount in the smallest currency unit - `consumerAmount`: The refund amount in the consumer's currency (optional) - `status`: Current refund status (`pending`, `failed`) - `reason`: The reason provided for the refund - `initiatedBy`: Who initiated the refund (merchantUser, apikey, admin) - `test`: Whether this is a test refund - `createdAt`: Timestamp when the refund was created - `updatedAt`: Timestamp of the last status update ## Listing refunds List all refunds with optional filtering: ```bash curl --request GET \ --url 'https://api.tokenz.one/v2/refunds?orderId=order_1p4LPTRKB5Z&limit=10' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### Query parameters - `orderId`: Filter refunds by order ID - `status`: Filter by refund status (`pending`, `failed`) - `limit`: Maximum number of refunds to return (1-100, default: 10) - `createdAfter`: Filter refunds created after this timestamp (ISO 8601) - `createdBefore`: Filter refunds created before this timestamp (ISO 8601) ### Response ```json { "refunds": { "items": [ { "id": "refund_1p4LS47fB1h", "object": "refund", "orderId": "order_1p4LPTRKB5Z", "amount": { "amount": 10000, "currency": "JPY" }, "consumerAmount": { "amount": 10000, "currency": "JPY" }, "status": "pending", "reason": "customer_cancellation", "initiatedBy": "apikey", "test": false, "createdAt": "2024-10-07T10:30:00Z", "updatedAt": "2024-10-07T10:30:00Z" } ], "hasMore": false } } ``` ## Refund webhooks Configure webhooks to receive notifications about refund events: ### `refund.created` Triggered when a refund is created: ```json { "id": "d4e5f6a7-b8c9-0123-defa-234567890123", "object": "refund.created", "createdAt": "2024-10-07T10:30:00Z", "test": false, "eventData": { "type": "refund", "version": "v2", "data": { "refund": { "id": "refund_1p4LS47fB1h", "object": "refund", "orderId": "order_1p4LPTRKB5Z", "amount": { "amount": 10000, "currency": "JPY" }, "consumerAmount": { "amount": 10000, "currency": "JPY" }, "status": "pending", "reason": "customer_cancellation", "initiatedBy": "apikey", "test": false, "createdAt": "2024-10-07T10:30:00Z", "updatedAt": "2024-10-07T10:30:00Z" } } } } ``` ### `refund.failed` Triggered when a refund fails: ```json { "id": "e5f6a7b8-c9d0-1234-efab-345678901234", "object": "refund.failed", "createdAt": "2024-10-07T10:40:00Z", "test": false, "eventData": { "type": "refund", "version": "v2", "data": { "refund": { "id": "refund_1p4LS47fB1h", "object": "refund", "orderId": "order_1p4LPTRKB5Z", "amount": { "amount": 10000, "currency": "JPY" }, "consumerAmount": { "amount": 10000, "currency": "JPY" }, "status": "failed", "reason": "customer_cancellation", "initiatedBy": "apikey", "test": false, "createdAt": "2024-10-07T10:30:00Z", "updatedAt": "2024-10-07T10:40:00Z" } } } } ``` ## Error handling The Refunds API returns standard HTTP status codes and detailed error messages: ### Common errors - `400 Bad Request`: Invalid request parameters or malformed request - `401 Unauthorized`: Invalid or missing API key - `403 Forbidden`: Insufficient permissions to perform the refund - `404 Not Found`: Order or refund not found - `422 Unprocessable Entity`: Business logic errors ### Error response format ```json { "status": 422, "code": "refund.amount-exceeds-available", "message": "Refund amount exceeds available refund amount for this order" } ``` ## Testing refunds Use test mode to develop and test your refund integration: 1. Use test API keys (prefixed with `test_`) 2. Create test orders using test checkout sessions 3. Test refunds will have `_t` suffix in their IDs (e.g., `refund_1p4LS47fB1h_t`) 4. Test webhooks are sent to your configured test webhook endpoints ## API reference ### Endpoints - `POST /v2/refunds` - Create a new refund - `GET /v2/refunds/{refundId}` - Retrieve a specific refund - `GET /v2/refunds` - List refunds with optional filters ### Authentication All endpoints require authentication via Bearer token: ``` Authorization: Bearer secret_test_YOUR_KEY_HERE ```