Rotate the merchant signer via setFactory
POST/settings/signer/rotationVerifies the outgoing-signer signatures, re-screens the stored settlement address, deploys the replacement PaymentFactory (same fee and registry, new signer) on every supported EVM chain, submits setFactory on each SubscriptionManager clone, and updates the stored merchant signer and factory address.
Headers
| Header | Description | Required |
|---|---|---|
| Authorization | Bearer token with your secret API key | yes |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| new_signer | string | yes | |
| rotations | object[] | yes |
rotations
| Field | Type | Required | Description |
|---|---|---|---|
| chain | string | yes | |
| deadline | integer | yes | |
| signature | string | yes |
Example Request
Request
const response = await fetch('https://checkout-api.exodus-int.com/settings/signer/rotation', {
method: 'POST',
headers: {
Authorization: 'Bearer sk_live_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"new_signer": "0x5678ef015678ef015678ef015678ef015678ef01",
"rotations": [
{
"chain": "eip155:11155111",
"deadline": 1798761600,
"signature": "0x0b30557a9fc4e90e33587da2c7ec11365b80a5caef14395e83a8cdf2173c6186abd0f51a3f6489aed3f81d42678cb1d6fb20456a8fb4d9fe23486d92b7dc01264b"
}
]
}),
});Responses
| Status | Description |
|---|---|
| 200 | The per-chain rotation results. |
| 400 | Validation error |
| 401 | A rotation signature does not recover to the signer. |
| 403 | API key lacks the required scope |
| 422 | Expired signature, unchanged signer, nothing to rotate, payments in flight, a concurrent rotation conflict, or a SubscriptionManager address that returned no data: no contract, a different contract, or a node that has not seen it yet (`manager_unreachable`). A settlement address that compliance screening rejects returns `type: cannot_process` with `code: flagged` before any deployment. |
| 502 | Replacement factory deployment failed before any relay (`deploy_failed`, `data.failed_chains`), or a `setFactory` relay failed after zero or more chains rotated (`rotation_partial_failure`). For partial failures `data.rotations` lists the chains that did rotate with their tx hashes, `data.failed_chain` names the failing chain, and `data.failed_tx_hash` carries the failed tx when one landed. Recover by re-fetching `GET /settings/signer/rotation` — rotated chains come back `already_rotated` — re-signing only the `pending` entries, and re-POSTing. |
| 503 | Settlement address screening is temporarily unavailable. Nothing was deployed or relayed; retry later with the same signatures while their deadlines hold. |
Response body
| Field | Type | Required | Description |
|---|---|---|---|
| object | enum: signer_rotation | yes | |
| new_signer | string | yes | |
| new_factory_address | string | yes | |
| rotations | object[] | yes |
rotations
| Field | Type | Required | Description |
|---|---|---|---|
| chain | string | yes | |
| status | enum: rotated | already_rotated | yes | |
| tx_hash | string | null | yes |
Example Response
{
"object": "signer_rotation",
"new_signer": "0x5678ef015678ef015678ef015678ef015678ef01",
"new_factory_address": "0xfaceb00cfaceb00cfaceb00cfaceb00cfaceb00c",
"rotations": [
{
"chain": "eip155:11155111",
"status": "rotated",
"tx_hash": "0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"
}
]
}Error Response
Error (e.g. 400)
{
"error": {
"type": "validation_error",
"message": "amount must be a positive number",
"param": "amount"
}
}