Settings
GET/settingsDescription
Retrieve your business configuration: business mode (test or live), per-chain signer status, and the addresses you need to integrate, including your PaymentFactory address (required to sign direct payments) and your settlement address.
These values are stable. Fetch them once and store them with your config. You can also view them in your dashboard.
Headers
| Header | Description | Required |
|---|---|---|
| Authorization | Bearer token with your API key. Required for API key authentication; omit when using dashboard session cookies. | no |
Example Request
const response = await fetch('https://checkout-api.exodus-int.com/settings', {
headers: {
Authorization: 'Bearer sk_live_xxxxxxxxxxxxxxxx',
},
});
const settings = await response.json();Response
{
"business_id": "biz_1234567890abcdef",
"business_name": "Acme Store",
"is_test": false,
"settlement_type": "CRYPTO",
"currency": null,
"settlement_provider": null,
"settlement_provider_id": null,
"can_generate_key": false,
"webhook_url": "https://yoursite.com/webhooks/exodus",
"chain_configs": [
{
"chain_family": "evm",
"signer_status": "active",
"merchant_signer": "0x1234abcd1234abcd1234abcd1234abcd1234abcd",
"settlement_address": "0xabcd1234abcd1234abcd1234abcd1234abcd1234",
"factory_address": "0xfaceb00cfaceb00cfaceb00cfaceb00cfaceb00c"
},
{
"chain_family": "solana",
"signer_status": "active",
"merchant_signer": "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin",
"settlement_address": "5tzFkiKscXHK5ZXCGbXZxdw7gTjjD1mBwuoFbhUvuAi9",
"factory_address": null
}
]
}Response Fields
| Field | Type | Description |
|---|---|---|
| business_id | string | Your business identifier. |
| business_name | string | Your business name. |
| is_test | boolean | true for a test business (testnets), false for a live business (mainnet). |
| settlement_type | string | 'CRYPTO' or 'FIAT'. How settlements are made for this business. |
| currency | string | null | Settlement currency. null for crypto settlement. |
| settlement_provider | string | null | The settlement provider used for this business. null for crypto settlement. |
| settlement_provider_id | string | null | Your identifier with the settlement provider. null for crypto settlement. |
| can_generate_key | boolean | Whether you can still generate a signing key for this business. |
| webhook_url | string | null | The configured webhook endpoint URL that receives event deliveries. null when webhooks are not configured. |
| chain_configs | array | One entry per chain family (evm, solana). |
| chain_configs[].chain_family | string | 'evm' or 'solana'. |
| chain_configs[].signer_status | string | 'not_configured', 'pending_activation', or 'active'. The addresses below are filled in as the config progresses to active. |
| chain_configs[].merchant_signer | string | null | The signing-key address registered for this chain family. |
| chain_configs[].settlement_address | string | null | Where settled funds are sent for this chain family. |
| chain_configs[].factory_address | string | null | EVM only: your PaymentFactory address, needed to sign direct payments. null until the config is active; always null for Solana (program-bound). |
POST/settings
Register a merchant signer
Register the merchant signer and settlement address for a chain family, activating signed-request verification for that chain. Both addresses must be valid for the chosen chain family. Returns 201 with the updated merchant settings.
Headers
| Header | Description | Required |
|---|---|---|
| Authorization | Bearer token with your API key. Required for API key authentication; omit when using dashboard session cookies. | no |
| Content-Type | application/json | yes |
Body
| Field | Type | Description |
|---|---|---|
| merchant_signer | string | Required. The signing-key address. Must be a valid address for the chain family. |
| chain_family | string | 'evm' or 'solana'. Defaults to 'evm'. |
| settlement_address | string | Required. Where settled funds are sent. Must be a valid address for the chain family. |
Example Request
const response = await fetch('https://checkout-api.exodus-int.com/settings', {
method: 'POST',
headers: {
Authorization: 'Bearer sk_live_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
merchant_signer: '0x1234abcd1234abcd1234abcd1234abcd1234abcd',
chain_family: 'evm',
settlement_address: '0xabcd1234abcd1234abcd1234abcd1234abcd1234',
}),
});
const settings = await response.json();Response
{
"business_id": "biz_1234567890abcdef",
"business_name": "Acme Store",
"is_test": false,
"settlement_type": "CRYPTO",
"currency": null,
"settlement_provider": null,
"settlement_provider_id": null,
"can_generate_key": false,
"webhook_url": "https://yoursite.com/webhooks/exodus",
"chain_configs": [
{
"chain_family": "evm",
"signer_status": "active",
"merchant_signer": "0x1234abcd1234abcd1234abcd1234abcd1234abcd",
"settlement_address": "0xabcd1234abcd1234abcd1234abcd1234abcd1234",
"factory_address": "0xfaceb00cfaceb00cfaceb00cfaceb00cfaceb00c"
}
]
}The response body matches the GET /settings response shape. See its Response Fields for a full description.
Returns 400 with error.type "validation_error" if merchant_signer or settlement_address is missing, or is not a valid address for the chosen chain_family.
PUT/settings
Update the settlement address
Update the settlement address for a chain family. New captures settle to the updated address. The address must be valid for the chosen chain family. Returns 200 with the updated merchant settings.
Headers
| Header | Description | Required |
|---|---|---|
| Authorization | Bearer token with your API key. Required for API key authentication; omit when using dashboard session cookies. | no |
| Content-Type | application/json | yes |
Body
| Field | Type | Description |
|---|---|---|
| chain_family | string | Required. 'evm' or 'solana'. |
| settlement_address | string | Required. Where settled funds are sent. Must be a valid address for the chain family. |
Example Request
const response = await fetch('https://checkout-api.exodus-int.com/settings', {
method: 'PUT',
headers: {
Authorization: 'Bearer sk_live_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
chain_family: 'evm',
settlement_address: '0xabcd1234abcd1234abcd1234abcd1234abcd1234',
}),
});
const settings = await response.json();Response
{
"business_id": "biz_1234567890abcdef",
"business_name": "Acme Store",
"is_test": false,
"settlement_type": "CRYPTO",
"currency": null,
"settlement_provider": null,
"settlement_provider_id": null,
"can_generate_key": false,
"webhook_url": "https://yoursite.com/webhooks/exodus",
"chain_configs": [
{
"chain_family": "evm",
"signer_status": "active",
"merchant_signer": "0x1234abcd1234abcd1234abcd1234abcd1234abcd",
"settlement_address": "0xabcd1234abcd1234abcd1234abcd1234abcd1234",
"factory_address": "0xfaceb00cfaceb00cfaceb00cfaceb00cfaceb00c"
}
]
}The response body matches the GET /settings response shape. See its Response Fields for a full description.
Returns 400 with error.type "validation_error" if chain_family or settlement_address is missing, or the address is not valid for the chosen chain_family.
PATCH/settings
Update the webhook URL
Set or update the webhook endpoint URL that receives event deliveries. Pass null to disable webhooks. Omitting webhook_url from the body returns the currently configured URL without changing it.
The webhook signing secret is generated automatically the first time you configure a webhook URL. On that first-time generation the response also includes webhook_secret, shown in full only in that response — store it securely. Subsequent updates to the URL do not return the secret and do not change it; use POST /settings/webhook/secret to rotate it.
Headers
| Header | Description | Required |
|---|---|---|
| Authorization | Bearer token with your API key. Required for API key authentication; omit when using dashboard session cookies. | no |
| Content-Type | application/json | yes |
Body
| Field | Type | Description |
|---|---|---|
| webhook_url | string | null | Optional. The webhook endpoint URL. Pass null to disable webhooks. Omit to leave the current URL unchanged. |
Example Request
const response = await fetch('https://checkout-api.exodus-int.com/settings', {
method: 'PATCH',
headers: {
Authorization: 'Bearer sk_live_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
webhook_url: 'https://yoursite.com/webhooks/exodus',
}),
});
const { webhook_url, webhook_secret } = await response.json();Response
{
"webhook_url": "https://yoursite.com/webhooks/exodus",
"webhook_secret": "9f8c7b6a5e4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b"
}Response Fields
| Field | Type | Description |
|---|---|---|
| webhook_url | string | null | The configured webhook URL. null when webhooks are disabled. |
| webhook_secret | string | The webhook signing secret. Only present when a secret is generated for the first time. Shown in full only in this response, so store it securely. |
Returns 400 with error.type "validation_error" if webhook_url is not a reachable, valid URL.
POST/settings/webhook/secret
Regenerate the webhook secret
Issue a new webhook signing secret. Rotation is zero-downtime: your previous secret keeps working for 24 hours, so deliveries never fail while you roll out the new one. During that window every event is signed with both secrets, so an endpoint validating against either keeps accepting events. previous_secret_expires_at in the response tells you when the old secret stops working. See Rotating your webhook secret for the full flow.
Your webhook secret is otherwise stable. It is generated once when you first configure a webhook URL and does not change when you update the URL, so call this only when you intend to rotate it. A webhook URL must be configured first.
Headers
| Header | Description | Required |
|---|---|---|
| Authorization | Bearer token with your API key. Required for API key authentication; omit when using dashboard session cookies. | no |
Example Request
const response = await fetch(
'https://checkout-api.exodus-int.com/settings/webhook/secret',
{
method: 'POST',
headers: {
Authorization: 'Bearer sk_live_xxxxxxxxxxxxxxxx',
},
},
);
const { webhook_secret, previous_secret_expires_at } = await response.json();Response
{
"webhook_secret": "9f8c7b6a5e4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b",
"previous_secret_expires_at": "2026-07-02T00:00:00.000Z"
}Response Fields
| Field | Type | Description |
|---|---|---|
| webhook_secret | string | The new signing secret. Shown in full only in this response, so store it securely. |
| previous_secret_expires_at | string | null | ISO 8601 timestamp when the previous secret stops being accepted (24 hours after rotation). During this window events are signed with both secrets. null when there was no previous secret to keep alive, for example the first time a secret is issued. |
Returns 422 with error.type "cannot_process" and error.code "webhook_not_configured" if no webhook URL is configured for the business.
POST/settings/webhook/test
Send a test webhook
Deliver a sample event to your configured webhook URL so you can confirm the endpoint is reachable and your signature verification works. The delivery is synchronous and is not recorded in your webhook history.
The test payload is a regular subscription.charge_succeeded event filled with placeholder data, signed with your real webhook secret. It carries a top-level "livemode": false field that marks it as a test; this field is test-only and does not appear on live events. A webhook URL must be configured first.
Headers
| Header | Description | Required |
|---|---|---|
| Authorization | Bearer token with your API key. Required for API key authentication; omit when using dashboard session cookies. | no |
Example Request
const response = await fetch(
'https://checkout-api.exodus-int.com/settings/webhook/test',
{
method: 'POST',
headers: {
Authorization: 'Bearer sk_live_xxxxxxxxxxxxxxxx',
},
},
);
const result = await response.json();Response
{
"object": "webhook_test",
"delivered": true,
"status": 200
}delivered is true when your endpoint returned a 2xx status. If it returned another status, delivered is false and status carries the code your endpoint returned. If your endpoint could not be reached, delivered is false and error describes the failure. Returns 422 with error.type "cannot_process" and error.code "webhook_not_configured" if no webhook URL is configured.
Response Fields
| Field | Type | Description |
|---|---|---|
| object | string | Always 'webhook_test'. |
| delivered | boolean | Whether your endpoint accepted the test delivery (2xx response). |
| status | number | The HTTP status your endpoint returned. Only present when a response was received. |
| error | string | Describes the failure. Only present when the endpoint could not be reached. |
