Prerequisites
- Payward Services API credentials (see the Authentication guide).
- A verified user with at least one account and on-chain quote trading enabled.
- A source wallet registered on the user’s withdrawal-address list as a same-owner address. The address must be approved before you create a quote.
- Enough source-asset balance in the wallet to settle the on-chain quote.
Workflow
Create an on-chain quote
Create a wallet-funded xStocks on-chain quote and receive the on-chain payload.
POST /v1/accounts/{account_id}/onchain-quotesSubmit the on-chain transaction
Call the Payward on-chain proxy contract with the returned payload before
expires_at.executeSwap(...)Quote lifecycle
| Status | Description |
|---|---|
pending | Quote is being prepared. Transitions to offered once the signed payload is ready, or to failed if preparation fails. |
offered | Quote created and locked. Valid until expires_at. |
executing | The on-chain transaction was observed and is awaiting confirmation. |
executed | Terminal. The on-chain quote completed. |
expired | Terminal. expires_at elapsed before settlement. |
failed | Terminal. The on-chain transaction reverted, or the offer could not be completed. |
Specifying the trade
Onchain quotes are restricted to xStock and USDC pairs. Set thewallet block on from — the quote is funded from the user’s wallet, not from the user’s Payward Services account balance.
| Field | Required | Description |
|---|---|---|
from.wallet | yes | { address, network }. Must be an approved same-owner withdrawal address. |
from.symbol | yes | Source asset symbol. Use USDC when buying xStocks, or the xStock when selling. |
from.type | yes | stablecoin or xstock. |
to.symbol | yes | Destination asset symbol. |
to.type | yes | stablecoin or xstock. |
from.amount or to.amount | one of | Set exactly one. The server calculates the other side. |
network value is ethereum.
Authentication setup
Authenticated endpoints require an HMAC-SHA512 request signature in theAPI-Sign header and a monotonically increasing nonce in the API-Nonce header. The helper below derives the signature from the URL path, request body, and nonce. See the Authentication guide for the full algorithm.
Step 1: create an on-chain quote
Send aPOST to /v1/accounts/{account_id}/onchain-quotes with from.wallet populated. The create response returns the full quote including execution_details, which carries the proxy contract address and the signed on-chain payload.
Step 2: submit the on-chain transaction
CallexecuteSwap on execution_details.proxy_address. Pass the returned proxy_swap_message before the quote expires.
The proxy call uses this argument shape:
Typescript
Step 3: poll for terminal status
After broadcasting on-chain, pollGET /v1/accounts/{account_id}/onchain-quotes/{quote_id} until status reaches a terminal value (executed, expired, or failed).
Reviewing on-chain quotes
List previously created on-chain quotes withGET /v1/accounts/{account_id}/onchain-quotes. Results are returned newest-first. Use page_token and page_size (defaults to 50, max 200) for pagination — next_page_token is omitted on the final page.
History entries omit
execution_details. The signed on-chain payload is only returned by the create response.Error handling
| HTTP status | Code | Cause | Remediation |
|---|---|---|---|
400 Bad Request | validation error | from.wallet.address is not an approved same-owner address. | Have the user add the wallet in the Payward UI and wait for approval. |
400 Bad Request | validation error | Both or neither of from.amount / to.amount were set. | Set exactly one side of the trade. |
400 Bad Request | validation error | from/to pair is not an xStock/USDC trade. | Restrict trades to xStock ↔ stablecoin pairs. |
403 Forbidden | forbidden | The user is not eligible for on-chain quote trading. | Confirm the user’s eligibility with your account manager. |
410 Gone | quote_expired | expires_at elapsed before settlement. | Request a fresh quote and broadcast more quickly. |
503 Service Unavailable | insufficient_liquidity | No liquidity is available at the requested size. | Retry with a smaller size. If it persists, contact support. |
Best practices
- Register wallets ahead of time. Screening can take time and will block quote creation until the address is approved.
- Store the on-chain quote create response. It is the only response that includes the signed on-chain execution payload.
- Treat
executed,expired, andfailedas terminal. Request a new quote for another attempt. - Submit on-chain well before
expires_at. Gas spikes and confirmation time reduce the usable window. - Capture
Request-Idfrom response headers. It speeds up support investigations.
API reference
| Endpoint | Method | Description |
|---|---|---|
/v1/accounts/{account_id}/onchain-quotes | POST | Create a wallet-funded on-chain quote. Returns the quote with execution_details. |
/v1/accounts/{account_id}/onchain-quotes | GET | List on-chain quotes for the authenticated user (paginated, newest first). |
/v1/accounts/{account_id}/onchain-quotes/{quote_id} | GET | Read on-chain quote status and amounts. Does not return a new execution payload. |