API Endpoints
All endpoints are prefixed with /v1
. Authentication uses JWT via an Authorization: Bearer <token>
header, obtained through the SIWE login flow.
Base URL:
https://instant-withdrawal-base.symmio.foundation/
2.1. POST /v1/fee-options
Fetch available withdrawal policies (fee & cooldown) for a given account and amount.
Request (Query Parameters):
account
(string; required; EVM address)amount
(integer; required; must be > 0; amount in wei)
Request Headers:
Authorization: Bearer <JWT>
Response Schema (200):
interface FeeOptionsResponseSchema {
count: number; // number of available options
options: FeeOption[];
}
interface FeeOption {
fee: number; // total fee in wei
cooldown: number; // cooldown period in seconds
user: string; // checksumed ETH address
amount: number; // requested amount in wei
validTime: number; // Unix epoch (seconds) when this option expires
}
Behavior:
Validates JWT and wallet ownership of account.
Checks if an existing pending request exists. If yes, returns error code for locked options.
Computes policies to determine the fees.
Error Codes:
11
unauthorized
The owner_address from JWT does not match the owner for provided account.
5
Already has pending withdrawal options try in seconds
A pending request already exists.
6
not enough user balance
The user’s on-chain balance is less than amount.
10
requested amount for bridge is very low
The requested amount is less than or equal to OPERATOR_FEE.
2.2. POST /v1/unlock/{account}
Clear any existing lock on fee policies for the given account, allowing immediate re-fetch of options.
Request:
account
(string; required; EVM address)
Request Headers:
Authorization: Bearer <JWT>
Response Schema (200):
interface UnlockAccountResponseSchema {
message: string; // "Account unlocked successfully."
}
Behavior:
Validates JWT and wallet ownership of account.
Removes pending fee options.
Returns
{ message: "Account <account> unlocked successfully." }
.
Error Codes:
11
unauthorized
The owner_address from JWT does not match the owner for provided account.
2.3. GET /v1/pending-fee-policy/{account}
Retrieve currently locked fee policies for the given account, if any exist.
Request:
account
(string; required; EVM address)
Request Headers:
Authorization: Bearer <JWT>
Response Schema (200):
interface FeeOptionsResponseSchema {
count: number; // number of available options
options: FeeOption[];
}
interface FeeOption {
fee: number; // total fee in wei
cooldown: number; // cooldown period in seconds
user: string; // checksumed ETH address
amount: number; // requested amount in wei
validTime: number; // Unix epoch (seconds) when this option expires
}
Behavior:
Validates JWT and wallet ownership of account.
Error Codes:
11
unauthorized
The owner_address from JWT does not match the owner for provided account.
2.4. GET /v1/max-instant-value/{account}
Fetch the maximum amount (in wei) that the user can withdraw instantly at this moment.
Request (Path Parameter):
account
(string; required; EVM address)
Request Headers:
Authorization: Bearer <JWT>
Response Schema (200):
interface MaxInstantWithdrawableAmountResponseSchema {
amount: number; // maximum instant-withdrawable amount in wei
}
Behavior:
Validates JWT and wallet ownership of account.
Checks user balance and risk factor.
Returns
{ amount: <max_instant> }
.
Error Codes:
11
unauthorized
The owner_address from JWT does not match the owner for provided account.
2.5. GET /v1/get-select-receiver-message?receiver={address}&bridgeId={bridgeId}
Construct an EIP‑712 typed-data payload that the user can sign to authorize selecting a different recipient (multi-account) for a given bridgeId.
Request (Query Parameters):
receiver
(string; required; checksumed EVM address)bridgeId
(integer; required)
Request Headers:
No JWT required (open endpoint)
Response Schema (200):
interface GetSelectReceiverMessageResponse {
payload: EIP712SelectReceiverMessage;
}
interface EIP712SelectReceiverMessage {
types: EIP712Types;
domain: EIP712DomainModel;
primaryType: "SelectReceiver";
message: {
receiver: string; // address
bridgeId: number;
};
}
Behavior: Returns an on‑chain domain and typed data structure, according to EIP‑712.
2.6. POST /v1/select-fee-policy
Submit a signed fee policy selection for an existing bridge transaction.
Request Body Schema (application/json):
interface SelectFeePolicyRequestSchema {
symmioBridgeId: number; // bridge transaction ID
cooldown: number; // chosen cooldown
feeAmount: number; // chosen fee (wei)
receiver?: SpecifiedReceiver | null; // optional new recipient object
}
interface SpecifiedReceiver {
address: string; // checksumed Ethereum address
signature: string; // EIP‑712 signature hex
}
Request Headers:
Authorization: Bearer <JWT>
Response Schema (200):
interface SelectFeePolicyResponseSchema {
bridge_id: number; // same as symmioBridgeId
execution_time: number; // Unix epoch (seconds) when `processWithdrawal` will be called
fee: number; // fee in wei
}
Behavior:
Validates JWT and that the current user is the owner of the
symmioBridgeId
account.Fetches BridgeTransaction from Symmio contract and validate data and status.
Calls
select_fee_policy_for_bridge
on-chain.Returns
{ bridge_id, fee: feeAmount, execution_time }
.
Error Codes:
11
unauthorized
The owner_address from JWT does not match the owner for provided account.
7
invalid bridge transaction
The provided bridgeId is not in RECEIVED status or does not point to the InstantWithdrawal contract.
8
invalid bridge policy option
No pending options exist for this user, or the selected fee/cooldown combination does not match any stored option.
9
You already selected a withdrawal option for bridge or it has executed.
A fee policy has already been selected for this bridge (bridge.bridge_type == instant
).
2.7. POST /v1/bridges/{account}/{start}/{size}
Search and paginate historical bridge transactions for a given user account:
Request:
account
(string; required; EVM address)start
(integer; required; offset index)size
(integer; required; page size)
Request Body Schema (application/json):
interface BridgeTransactionRequestModel {
bridge_state?: "pending" | "executed" | "settled" | "suspend" | null;
bridge_type?: "instant" | "after_cool_down" | "no_policy" | null;
}
Request Headers:
Authorization: Bearer <JWT>
Response Schema (200):
interface BridgeTransactionSearchResponseSchema { count: number; bridges: BridgeTransactionResponseModel[] | null; } interface BridgeTransactionResponseModel { bridge_id: number; user_address: string; bridge_state: "pending" | "executed" | "settled" | "suspend"; bridge_type: "instant" | "after_cool_down" | "no_policy"; bridge_amount: number; // in wei fee_amount: number; // in wei bridge_transaction_time: number; // Unix epoch seconds execution_time?: number; // Unix epoch seconds or null }
Behavior:
Validates JWT and wallet ownership of account.
Queries database, ordering by creation time descending.
If no records, returns
{ count: 0, bridges: null }
.Otherwise returns
{ count: <number_of_rows>, bridges: [ ... ] }
.
Error Codes:
CodeMessageCondition11
unauthorized
The owner_address from JWT does not match the owner for provided account.
2.8 GET /v1/withdrawal-config
Fetch the current withdrawal settings.
Request:
No Parameters
Request Headers:
Authorization: Bearer<JWT>
Response Schema (200):
interface WithdrawalSettingsResponseSchema {
operatorFee: number;
maxInstantAmount: number;
instantFeeRate: number;
policyValidTime: number;
minWithdrawalCooldown: number;
}
2.9 Authentication Endpoints
2.9.1. POST /v1/auth/nonce
Request a one-time nonce for SIWE login:
Request Body (application/json):
interface AddressSchema { address: string; // checksumed Ethereum address }
Response (200):
{ "nonce": "0x1234…abcd" }
Behavior:
Generates random nonce for the address.
Error Codes:
ValueError (missing or malformed address)
2.9.2. GET /v1/auth/sign-in-message
Returns a Sign‑In With Ethereum (SIWE/EIP-4361) message that the user must sign.
Request (Query):
address
(string; required, EVM address)domain
(string; required)uri
(string; required)statement
(string; optional)version
(string; optional)
Response Schema (200):
interface SignInMessageResponseSchema { message: string; params: SignInMessageParams; } interface SignInMessageParams { address: string; // Same as the `address` query param domain: string; // Same as the `domain` query param uri: string; // Same as the `uri` query param statement?: string; // Same as the `statement` query param version: string; // Same as the `version` query param chainId: number; // Backend’s configured chain ID nonce: string; // Newly generated 16-byte hex string issuedAt: string; // UTC timestamp in ISO 8601 format }
Behavior
Constructs a full EIP-4361-formatted message string comprising
Returns both the single message string and the underlying data object.
The UI shows message in the wallet’s signing modal and keeps the returned data for the subsequent POST /v1/auth/login call.
2.9.3. POST /v1/auth/login
Validate signed SIWE message and issue JWT:
Request Body:
interface LoginRequest { message: CustomSiweMessage; // full EIP‑4361 payload signature: string; // hex signature } interface CustomSiweMessage { domain: string; address: string; uri: string; version: string; chainId: number; issuedAt: string; nonce: string; statement?: string; expirationTime?: string; }
Response Schema (200):
interface Token { access_token: string; // JWT token_type: string; // "bearer" }
Error Codes:
CodeMessageCondition14
expired_nonce
No nonce found or expired.
18
nonce_mismatch
Provided nonce differs from stored.
12
invalid_signature
Signature verification failed.
2.8.4. GET /v1/auth/me
Retrieve the currently authenticated user address:
Request Headers:
Authorization: Bearer <JWT>
Response (200):
interface AddressSchema { address: string; // checksumed Ethereum address }
Error Codes:
CodeMessageCondition11
unauthorized
The owner_address from JWT does not match the owner for provided account.
Bridge Enums Overview
Bridge States:
pending
The bridge transaction is recorded but process withdrawal has not been called yet.
executed
A fee policy was selected, and the withdrawal has been executed on-chain.
settled
The funds have been withdrawn from Symmio to the bridge.
suspend
The bridge process is on hold (e.g., due to a suspension from Symmio).
Bridge Types:
instant
The user chose an instant-withdrawal policy with custom fee and cooldown.
after_cool_down
The user selected the default policy that requires waiting for Symmio cooldown before withdrawal.
no_policy
No fee policy has been chosen yet; the bridge is awaiting the user to request options and select one.
Last updated