Remove Delegated Signer
Remove a delegated signer from a subaccount, revoking their ability to perform trading actions on behalf of the subaccount. This immediately terminates the trading permission previously granted to the specified wallet address.
Endpoint
POST https://papi.synthetix.io/v1/tradeRequest
Request Format
{
"params": {
"action": "removeDelegatedSigner",
"subAccountId": "1867542890123456789",
"delegateAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f89590"
},
"nonce": 1735689600000,
"expiresAfter": 1735689900000,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
params | object | Yes | Action object containing removal details |
params.action | string | Yes | Must be "removeDelegatedSigner" |
params.subAccountId | string | Yes | The subaccount ID to remove the delegated signer from |
params.delegateAddress | string | Yes | Ethereum wallet address of the delegated signer to remove (42-character hex format) |
expiresAfter | integer | No | Optional request expiration timestamp (milliseconds) |
| Parameter | Type | Required | Description |
|---|---|---|---|
nonce | uint64 | Yes* | Unix milliseconds timestamp (must be monotonically increasing) |
signature | object | Yes | EIP-712 signature object |
expiresAfter | uint64 | No | Unix seconds expiration timestamp (5x rate limit on stale cancels) |
:::info Common Parameters
These are top-level request parameters. The subAccountId parameter is specified within the params object (see each endpoint's parameter table).
:::
:::info SubAccountAction Endpoints
Endpoints using SubAccountAction signing (getPositions, getOpenOrders, getOrdersHistory, getTrades, getFundingPayments, getSubAccount, getDelegatedSigners, getBalanceUpdates) do not require the nonce parameter. Only signature and optional expiresAfter are needed.
:::
EIP-712 Signature Structure
The request is signed using EIP-712 with the following type definition:
EIP-712 Type Definitions for Delegation
AddDelegatedSigner
const AddDelegatedSignerTypes = {
AddDelegatedSigner: [
{ name: "delegateAddress", type: "address" },
{ name: "subAccountId", type: "uint256" },
{ name: "nonce", type: "uint256" },
{ name: "expiresAfter", type: "uint256" },
{ name: "expiresAt", type: "uint256" },
{ name: "permissions", type: "string[]" }
]
}GetDelegatedSigners
Uses the standard SubAccountAction type (same as other read operations like getTrades, getPositions):
const SubAccountActionTypes = {
SubAccountAction: [
{ name: "subAccountId", type: "uint256" },
{ name: "action", type: "string" },
{ name: "expiresAfter", type: "uint256" }
]
}
// Message example:
const message = {
subAccountId: "1867542890123456789",
action: "getDelegatedSigners",
expiresAfter: 0 // Optional, use 0 if not expiring
}RemoveDelegatedSigner
const RemoveDelegatedSignerTypes = {
RemoveDelegatedSigner: [
{ name: "delegateAddress", type: "address" },
{ name: "subAccountId", type: "uint256" },
{ name: "nonce", type: "uint256" },
{ name: "expiresAfter", type: "uint256" }
]
}Example Typed Data for AddDelegatedSigner
{
"types": {
"EIP712Domain": [
{ "name": "name", "type": "string" },
{ "name": "version", "type": "string" },
{ "name": "chainId", "type": "uint256" },
{ "name": "verifyingContract", "type": "address" }
],
"AddDelegatedSigner": [
{ "name": "delegateAddress", "type": "address" },
{ "name": "subAccountId", "type": "uint256" },
{ "name": "nonce", "type": "uint256" },
{ "name": "expiresAfter", "type": "uint256" },
{ "name": "expiresAt", "type": "uint256" },
{ "name": "permissions", "type": "string[]" }
]
},
"primaryType": "AddDelegatedSigner",
"domain": {
"name": "Synthetix",
"version": "1",
"chainId": 1,
"verifyingContract": "0x0000000000000000000000000000000000000000"
},
"message": {
"delegateAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f89590",
"subAccountId": "1867542890123456789",
"nonce": 1735689600000,
"expiresAfter": 1735689900000,
"expiresAt": 0,
"permissions": ["trading"]
}
}Important Notes:
- Field order matters for EIP-712 - Fields must be in the exact order shown above for signature verification
delegateAddressis the wallet address being granted delegation permissionsexpiresAfteris the request expiration timestamp (when the request itself expires)expiresAtis when the delegation permission expires (use0for no expiration)- The
noncefield must be monotonically increasing per subaccount - All delegation operations must be signed by the master account owner
Response
Success Response
{
"status": "ok",
"response": {
"subAccountId": "1867542890123456789",
"walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f89590"
},
"request_id": "5ccf215d37e3ae6d"
}Response Fields
| Field | Type | Description |
|---|---|---|
subAccountId | string | The subaccount ID the signer was removed from |
walletAddress | string | The removed delegated signer's wallet address |
Error Response
{
"status": "error",
"error": {
"message": "Delegated signer not found",
"code": "NOT_FOUND"
},
"request_id": "5ccf215d37e3ae6d"
}Common Error Cases
{
"status": "error",
"error": {
"message": "Only master account can remove delegated signers",
"code": "UNAUTHORIZED"
},
"request_id": "5ccf215d37e3ae6d"
}{
"status": "error",
"error": {
"message": "Subaccount not found",
"code": "NOT_FOUND"
},
"request_id": "5ccf215d37e3ae6d"
}Code Examples
Remove Trading Bot Access
{
"params": {
"action": "removeDelegatedSigner",
"subAccountId": "1867542890123456789",
"delegateAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f89590"
},
"nonce": 1735689600000,
"expiresAfter": 1735689900000,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}Revoke Team Member Access
{
"params": {
"action": "removeDelegatedSigner",
"subAccountId": "1867542890123456789",
"delegateAddress": "0x9C4b8E7F0A2D3B6C5E8A1F3D5B7C9E1A3F5D7B9E"
},
"nonce": 1735689600001,
"expiresAfter": 1735689900000,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}Implementation Notes
- Immediate Effect: Removal takes effect immediately upon successful execution
- Access Requirements: Only master account owners can remove delegated signers
- No Self-Removal: Delegated signers cannot remove themselves (must be done by master account)
- Idempotent: Attempting to remove a non-existent delegation returns an error
- Active Sessions: Any active sessions or connections for the removed signer should be terminated
- Pending Operations: Any pending operations initiated by the removed signer remain valid
- Audit Trail: All removal actions are logged for security and compliance
Security Considerations
- Master Account Only: System validates that only the master account can remove delegated signers
- Address Validation: Wallet addresses must be valid Ethereum addresses
- Signature Required: All removal operations require valid EIP-712 signatures
- No Cascade: Removing a delegated signer does not affect any other delegations
- Recovery: Removed signers can be re-added if needed through the
addDelegatedSignerendpoint
Effect on Active Operations
| Operation Type | Effect of Removal |
|---|---|
| Open Orders | Remain active (can be cancelled by master account) |
| Pending Withdrawals | Continue processing |
| Active Sessions | Should be terminated |
| API Keys | Should be invalidated |
| Subscriptions | Should be cancelled |
Use Cases
- Security Response: Immediately revoke access when a delegated signer is compromised
- Team Changes: Remove access when team members leave or change roles
- Bot Decommission: Remove trading bot access when no longer needed
- Access Rotation: Regular removal and re-addition of signers for security
- Emergency Lockdown: Quick removal of all delegated signers in security events
Signing
All trading methods are signed using EIP-712. Each successful trading request will contain:
- A piece of structured data that includes the sender address
- A signature of the hash of that structured data, signed by the sender
For detailed information on EIP-712 signing, see EIP-712 Signing.
Nonce Management
The nonce system prevents replay attacks and ensures order uniqueness:
- Use current timestamp in milliseconds as nonce
- Each nonce must be greater than the previous one
- Recommended: Use
Date.now()or equivalent - If nonce conflicts occur, increment by 1 and retry
:::note SubAccountAction Exception
SubAccountAction endpoints (getPositions, getOpenOrders, getOrdersHistory, getTrades, getFundingPayments, getSubAccount, getDelegatedSigners, getBalanceUpdates) do not require a nonce. Only the signature and optional expiresAfter parameters are needed.
:::
Error Handling
| Error | Description |
|---|---|
| Invalid signature | EIP-712 signature validation failed |
| Invalid market symbol | Market symbol not recognized |
| Nonce already used | Nonce must be greater than previous value |
| Rate limit exceeded | Too many requests in time window |
| Request expired | expiresAfter timestamp has passed |