Update a subscription charge's metadata
PATCH/merchants/{merchantId}/charges/{chargeId}Replace the metadata object on a subscription charge. Use this to attach a reconciliation reference (invoice, order, or ledger id) after the fact — in particular when a charge relay request failed after the on-chain charge settled, so the metadata never persisted. Discover the charge via the list endpoint (filter by subscription_id, match on charge_nonce or tx_hash). The metadata is replaced wholesale, not merged; send { "metadata": {} } to clear it.
Headers
| Header | Description | Required |
|---|---|---|
| Authorization | Bearer token with your secret API key | yes |
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchantId | string | yes | |
| chargeId | string | yes |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| metadata | object | yes | Flat map of merchant-defined references. Up to 50 keys; keys up to 40 characters; values are strings up to 500 characters (nested values are rejected). |
Example Request
Request
const response = await fetch('https://checkout-api.exodus-int.com/merchants/<merchantId>/charges/<chargeId>', {
method: 'PATCH',
headers: {
Authorization: 'Bearer sk_live_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"metadata": {
"invoice_id": "inv_202605"
}
}),
});Responses
| Status | Description |
|---|---|
| 200 | The charge with its updated metadata. |
| 400 | Validation error |
| 401 | Missing or invalid authentication |
| 403 | API key lacks the required scope |
| 404 | Resource not found |
Response body
| Field | Type | Required | Description |
|---|---|---|---|
| object | enum: subscription_charge | yes | |
| id | string | yes | |
| subscription_id | string | yes | |
| subscriber | string | yes | |
| amount | string | yes | |
| fee | string | yes | |
| tx_hash | string | null | yes | |
| chain | string | yes | |
| charge_nonce | number | yes | |
| charged_at | string | yes | |
| status | enum: succeeded | failed | yes | |
| failure_reason | string | null | yes | |
| block_number | string | yes | |
| metadata | object | null | yes | |
| created_at | string | yes |
Example Response
{
"object": "subscription_charge",
"id": "subc_6789abcdef012345",
"subscription_id": "0x9f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a",
"subscriber": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE21",
"amount": "9990000",
"fee": "0",
"tx_hash": "0x8a9c67b2d1e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9",
"chain": "eip155:1",
"charge_nonce": 3,
"charged_at": "2026-05-19T12:02:18Z",
"status": "succeeded",
"failure_reason": null,
"block_number": "12346789",
"metadata": {
"invoice_id": "inv_202605"
},
"created_at": "2026-05-19T12:02:18Z"
}Error Response
Error (e.g. 400)
{
"error": {
"type": "validation_error",
"message": "amount must be a positive number",
"param": "amount"
}
}