Skip to main content
Partners can buy a Pack from the public catalogue for an owned managed server-wallet sub-account, then claim its winnings after settlement. The backend handles signing and sponsored on-chain submission. Custom baskets and RFQ purchases are outside this API, and partner revenue share is not included. Use SDK 1.3.0 or later: TypeScript, Python, Go, or Rust.

Authentication and account selection

Keep partner credentials on your server. Every /parlay/partner/* route requires HMAC authentication with trading and delegated_signing. Allowance checks and repair additionally require account_creation. Do not set x-on-behalf-of as a global client header. The SDKs apply delegation to position reads and put the account ID in the body for writes. A pack ID identifies the catalogue product; a position ID identifies one purchase.

Buy workflow

1. Choose a Pack

Use List Packs, Search Packs, or Get Pack. Listing and search return active, eligible Packs within their trade window. Detail can return a closed Pack, so fetching a Pack by ID does not guarantee it can be bought. The catalogue’s payout is a display estimate for a 10 USDC stake, expressed in human-readable USDC. Request a partner quote for the intended stake instead of copying that estimate into a buy request.

2. Confirm the Pack vault allowance

Before preparing a short-lived quote and buy intent:
  1. Call Check Partner Account Allowances.
  2. Find the USDC_ALLOWANCE target labelled parlay-treasury-vault.
  3. Require confirmed: true and status: "confirmed" for that target.
  4. If approval is missing, call Retry Partner Account Allowances, then poll GET with a bounded wait until confirmed. A submitted target is still pending.
Repair follows the existing unlimited-approval policy and may repair other missing trading approvals too. If the vault target is absent, stop and check the environment’s Pack vault configuration. Do not treat an empty target list or a generic readiness flag as proof of Pack approval. When the wallet already has sufficient USDC allowance, buying skips permit calls. Code-bearing managed wallets, including delegated EIP-7702 wallets, require a standing vault allowance; they cannot use the EOA permit fallback. An insufficient allowance can return 409 PACK_ALLOWANCE_REQUIRED with tokenAddress, spender, and requiredAllowance. Compare these with the allowance target when diagnosing a failure.

3. Quote and save a purchase request

Call Quote Pack:
Amounts in quote and buy requests are integer micro-USDC strings: "1000000" is 1 USDC. Avoid floating-point conversions. An ineligible quote can contain only:
Always check eligible before using optional pricing fields. An eligible quote is advisory; it does not reserve a price or liquidity. Build the buy request from the quote: The SDK payout helper floors potentialPayout × (10000 − slippageBps) / 10000 using integer arithmetic. For example, 100 basis points allows a 1% reduction in total payout. This is a payout floor, not an extra fee. Persist the entire request before submitting it. Associate it with your environment, partner identity, managed profile, and application purchase ID. Enforce one saved request per intended purchase so concurrent workers cannot create different keys. Keep credentials out of the journal.

4. Submit and wait for minting

Call Buy Pack with the saved request. Store the returned position ID and transaction hash when available.
Position FAILED is recoverable. It does not prove the purchase was never submitted. Starting a second purchase with a new key while the first is recovering can buy the Pack twice.
Use partner position reads to track in-flight purchases; the public portfolio excludes pending and failed positions. All four SDKs provide bounded mint polling. If polling expires, replay the identical saved buy request, including its original deadline, to obtain the backend’s recovery state. A timeout, disconnect, 5xx response, or locally expired deadline is not permission to change the request. Replaying the same key and body retrieves or resumes the original operation. Changing a field while keeping the key is invalid; changing the key creates a separate purchase.

Recover buy errors

Use each SDK’s typed Pack error classifier to read the API’s recovery metadata. Classification does not retry, repair an allowance, or change an idempotency key. Do not interpret a generic 401 as an expired-intent rejection. If an error includes NOT_SUBMITTED as well as a cause code, use the explicit submission state to choose the recovery path.

Claim a winning position

After the markets settle, read the position and require status: "WON". Claim using its position ID, not its catalogue Pack ID:
Include freshly signed HMAC headers on each call. Repeat the same claim request to advance the durable operation: The SDK claim helper repeats this workflow with a bounded wait. claimOnce / claim_once / ClaimOnce performs a single step when you manage scheduling yourself. All claim helpers surface API errors; they do not automatically retry every error.
  • On 429 or a wallet-busy conflict, wait and resume the same position’s claim.
  • On PACK_TRANSACTION_REVERTED, inspect the failed transaction, address the cause, and resume the same claim.
  • On PACK_SUBMISSION_UNKNOWN, stop blind retries and reconcile the on-chain submission.
For a lost submission response, call Confirm Claim with the mined factory redemption transaction hash and the same onBehalfOf. The backend verifies the successful receipt and redemption event against the expected token and recipient. Do not pass the buy hash, approval hash, or userOperationHash. The payout goes to the managed wallet. A sponsored transaction’s sender may be a bundler; inspect receipt events and transfers for the recipient. The position’s settlement status remains WON after claiming: use the claim response’s CLAIMED status and the position’s claimTxHash to verify completion.

Pacing and polling

The partner routes share a limit of 10 requests per 10 seconds per partner owner, across sub-accounts and workers. On 429, the response includes retryAfterSeconds: 10. Reuse one SDK client per partner. Its Packs service serializes calls with at least 1.1 seconds between starts and defers subsequent calls after a 429. Coordinate separate clients and processes yourself. This pacing does not automatically replay a failed write. Mint and claim polling default to 60 attempts with a 5-second interval. TypeScript, Python, and Rust expose polling options; Go supports cancellation through the request context. When a bounded wait ends, retain the purchase or claim identity and resume it.