Skip to main content

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 flowUse the Dapp embed insteadCall contracts yourself
Native wallet, browser extension, or mobile appWeb Dapp with a hosted quote boxYou run matching off-chain
You control quote UX and offer rankingYou want zero backend codeSettle matched intents with your own RFQ / Call the CLOB
You have (or can get) an API taker organizationReferral-only monetization is enoughNo 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:

  1. Create API key: requires an admin personal_sign over a challenge (not just SIWE session login).
  2. Copy the secret immediately; it is shown once.
  3. 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):

MethodPathPurpose
GET/api/taker/keysList keys
POST/api/taker/keys/challengeChallenge for add/remove key
POST/api/taker/keysCreate key (signed)
DELETE/api/taker/keys/:idRevoke 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/quote and POST /api/margin/quote (when Borrow is live)
  • Must match taker_address / borrower_address in the quote body (403 on 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.

EventMeaning
rfq_offerNew signed maker offer. rank and show in your UI
rfq_requestQuote / Dutch phase updates
rfq_resultFill 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:

  1. Resolve mothership address from GET /api/networks for the chain.
  2. 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.
  3. Call mothership executeFixedPackageIntent with:
    • Maker-signed package request from the offer
    • directions, taker_salt, and referrer from the quote
    • takerPermits (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):

BucketTypical use
Delegate mintPOST /api/taker/delegate
Quote createPOST /api/quote with delegate JWT
Open quotesSimultaneous 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 referrer on POST /api/quote (your wallet, or omit for address(0)). It is hashed into taker_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​

StepOwner
Taker org provisionedOpshuns admin
Org API key on backend onlyYou
Delegate JWT per user sessionYour backend
taker_address matches delegateYour backend
Pair (CLOB) exists for token tripleOn-chain / GET /api/networks
Stream or poll for offersYour backend / app
Approvals + executeFixedPackageIntentUser wallet