Add to your crypto wallet (API taker flow)
Build options RFQ into a wallet or mobile app with your own UI. Your backend opens quote windows through the Opshuns API; the user’s wallet signs approvals and executeFixedPackageIntent on-chain.
This is the integration path for wallets that cannot iframe a web widget and need server-assisted quote create without a Turnstile widget on every request.
When to use this
| Use the API taker flow | Use the Dapp embed instead | Call contracts yourself |
|---|---|---|
| Native wallet, browser extension, or mobile app | Web Dapp with a hosted quote box | You run matching off-chain |
| You control quote UX and offer ranking | You want zero backend code | Settle matched intents with your own RFQ / Call the CLOB |
| You have (or can get) an API taker organization | Referral-only monetization is enough | No Opshuns auction required |
Prefer @opshuns/sdk on the backend for createTakerDelegateWithSigner, createQuoteSession, and signing helpers. TypeScript SDK.
Architecture
Wallet app (your UI)
│
├─ Your backend (org API key, never in the client)
│ ├─ POST /api/taker/delegate { address: user }
│ │ → short-lived delegate JWT (bound to user address)
│ ├─ POST /api/quote Authorization: Bearer <delegate>
│ │ → quote + stream_token
│ └─ (optional) proxy WebSocket to rfq_stream:<stream_token>
│
└─ User wallet
├─ ERC-20 approve / Permit2 (package premium ± underlying ± live fees)
└─ mothership executeFixedPackageIntent(…, directions, takerSalt, takerPermits, referrer)
Makers never receive the raw taker address on the public feed. Offers bind to taker_address_hash, which includes the user address, salt, per-leg directions, and referrer.
1. Get an API taker organization
API taker orgs are provisioned by Opshuns (admin API Takers tab). Each org has:
- An admin wallet (SIWE login for key management)
- A key limit (long-lived backend secrets)
- Rate limits on delegate mint and quote create (per-org overrides possible)
Contact Opshuns or your account admin to be added as a taker organization.
2. Issue a backend API key
The org admin signs in at https://api.testnet.opshuns.com/taker with the admin wallet (must match the org’s admin_address).
From the org console:
- Create API key: requires an admin
personal_signover a challenge (not just SIWE session login). - Copy the secret immediately; it is shown once.
- Store it only on your backend. Never ship it in a mobile app or browser bundle.
Use the secret as:
Authorization: Bearer <org-api-key-secret>
Key management API (admin SIWE or org key where noted):
| Method | Path | Purpose |
|---|---|---|
GET | /api/taker/keys | List keys |
POST | /api/taker/keys/challenge | Challenge for add/remove key |
POST | /api/taker/keys | Create key (signed) |
DELETE | /api/taker/keys/:id | Revoke key (signed) |
3. Mint a per-user delegate session
Before each quote (or when refreshing an expired session), your backend calls:
POST /api/taker/delegate
{
"address": "0xUserWallet",
"expires_in": 300
}
With Authorization: Bearer <org-api-key-secret>.
Response
{
"token": "short-lived-delegate-jwt",
"address": "0xuserwallet",
"expires_in": 300,
"organization_id": "…"
}
The delegate JWT:
- Skips Turnstile on
POST /api/quoteandPOST /api/margin/quote(when Borrow is live) - Must match
taker_address/borrower_addressin the quote body (403on mismatch) - Expires quickly (default max age is configured server-side, often ~300s)
- Can access explore / loan-data routes only when minted with a taker API key (not SIWE-minted delegates from the admin UI). See Explore & loan data auth.
Org admins can also mint delegates from the https://api.testnet.opshuns.com/taker UI (wallet-signed delegate action) for testing.
4. Open an options RFQ
POST /api/quote with the delegate JWT:
Authorization: Bearer <delegate-jwt>
Content-Type: application/json
{
"chain_id": 31337,
"taker_address": "0xUserWallet",
"polarity": "b_is_buy",
"expires_in": 60,
"referrer": "0xYourWallet",
"intents": [
{
"opshuns6909_contract": "0xPairClob",
"option_type": "call",
"structure": 0,
"start_exercise_timestamp": 0,
"expiry_timestamp": 1785950335,
"strike_wad": "2500000000",
"amount": "1000000000000000000"
}
]
}
Response (abbreviated):
{
"quote": {
"id": "…",
"taker_address_hash": "0x…",
"taker_salt": "…",
"directions": [1],
"state": "open"
},
"stream_token": "…",
"topic": "rfq_stream:…"
}
Full request shapes, polarity, multi-leg strategies, and Dutch mode: API-only option quotes.
Poll with GET /api/quote/:id?stream_token=… or stream (below).
5. Stream maker offers
Connect a Phoenix socket to <ApiOrigin path="/socket" /> and join rfq_stream:<stream_token> from the create response.
| Event | Meaning |
|---|---|
rfq_offer | New signed maker offer. rank and show in your UI |
rfq_request | Quote / Dutch phase updates |
rfq_result | Fill outcome |
Details: WebSockets & pubsub.
Join the stream before or immediately after create so you do not miss early offers. Quote windows are short (expires_in, typically ≤ 300s).
6. Settle on-chain (user wallet)
When the user picks an offer:
- Resolve mothership address from
GET /api/networksfor the chain. - Approve ERC-20 pulls (and/or Permit2) for the package premium and/or underlying per
quote.directions, plus the live protocol fee (half when the maker funds that leg) and referral. See Fees. - Call mothership
executeFixedPackageIntentwith:- Maker-signed package request from the offer
directions,taker_salt, andreferrerfrom the quotetakerPermits(empty array ⇒ allowance-only pulls)
FixedPackage is the standard RFQ path. Inventory executeIntent is zero-premium only. Dutch and Authority use different mothership entrypoints: On-chain fill modes.
The trading app’s settlement helpers live in the web monorepo (executeIntent, pull detection, fee quoting) if you want a reference implementation.
Rate limits and concurrency
API taker orgs have per-org limits (defaults in admin Rate limits; overrides on the org):
| Bucket | Typical use |
|---|---|
| Delegate mint | POST /api/taker/delegate |
| Quote create | POST /api/quote with delegate JWT |
| Open quotes | Simultaneous live RFQ (+ margin RFQ when live) processes per org |
Over-limit responses are 429 (too many requests / too many open quotes). Delegate and quote buckets may apply tarpit delay before 429.
Monetization
- Referral: set
referreronPOST /api/quote(your wallet, or omit foraddress(0)). It is hashed intotaker_address_hash; the fill must pass the same address. Rates: Fees. Referral is not halved when the maker pays a leg. - No protocol share to integrators beyond referral unless separately agreed.
Checklist
| Step | Owner |
|---|---|
| Taker org provisioned | Opshuns admin |
| Org API key on backend only | You |
| Delegate JWT per user session | Your backend |
taker_address matches delegate | Your backend |
| Pair (CLOB) exists for token triple | On-chain / GET /api/networks |
| Stream or poll for offers | Your backend / app |
Approvals + executeFixedPackageIntent | User wallet |
Related
- TypeScript SDK:
@opshuns/sdkfrom../sdk - API overview: endpoint map
- API-only option quotes: intents, polarity, spreads
- Authentication (SIWE): maker vs taker auth (taker org uses
/api/taker/*, not maker keys) - Explore & loan data auth. CLOB / loan analytics for integrators
- Trading app: reference UX for quote box behavior
- Dapp embed: iframe alternative
- Settle matched intents with your own RFQ. skip Opshuns auction
- Call the CLOB directly. book-only