Skip to content

Relay REST API

The Relay REST API submits signed Kuru trading actions without requiring the trading wallet to hold native gas tokens.

POST https://api.relay.testnet.kuru.io/relay
Authorization: Bearer <JWT bound to the trading wallet>
Content-Type: application/json

The REST surface has two authentication endpoints and one transaction endpoint. First obtain a wallet-bound JWT from /auth/challenge and /auth/token; then send typed actions to /relay. On /relay, the method field selects the action and payload contains that method's signed data.

Use two wallets with different responsibilities:

Identity Responsibility
Main wallet Owns or administers the AccountCore account. Keeps custody and grants or revokes trading permission.
Secondary trading EOA Controlled by a passkey or embedded wallet. Receives only TRADE, delegates itself through EIP-7702, and signs trading intents.
Relay sponsor Pays gas and broadcasts the outer transaction. It cannot create or modify the user's signed intent.

Do not delegate the user's main wallet merely to enable one-click trading. A separate trading EOA limits the effect of a lost session key and lets the main wallet revoke trading rights independently.

The secondary wallet provider is your choice. An embedded or passkey-backed EOA from a provider such as Privy or Mera can be used if it can sign the required secp256k1 EIP-712 messages and EIP-7702 authorization.

Complete flow

1. Create the trading wallet

Create a fresh secondary EOA. In static-allowlist deployments, the operator must admit it first. In allow-all deployments, every valid nonzero EOA is admitted automatically and can proceed directly to authentication.

Request a challenge from the relay, sign its exact message with the secondary EOA, and exchange the signature for a short-lived JWT. See Authentication and JWTs for the complete request and response flow.

2. Onboard it

The main wallet signs an AccountCore authorization granting the secondary EOA TRADE. The secondary EOA signs an EIP-7702 authorization delegating itself to KuruTradingWallet.

Submit both in one account_core.authorize_account_signer_by_sig request. See Onboard a trading wallet.

3. Confirm onboarding

Wait for the transaction receipt and verify both:

  • the secondary EOA contains the expected EIP-7702 delegation indicator; and
  • AccountCore emitted AccountSignerAuthorized for that EOA with TRADE permission.

Do not send orders merely because the relay returned BROADCAST.

4. Trade

The secondary EOA signs KuruTradingWallet EIP-712 intents and submits them with either:

  • wallet.execute_batch for readable native orders and slot cancellations; or
  • wallet.execute_replace_by_slot_packed for the compact, lower-calldata format.

See Place and cancel orders.

5. Track the transaction

Store the relay requestId, returned txHash, intent nonce, and clientOrderId. Follow the receipt independently and verify IntentExecuted plus the expected orderbook change.

6. Revoke when the session ends

The AccountCore owner or administrator revokes the secondary EOA's trading permission through AccountCore. Revocation is not currently exposed as a public relay method, so integrations must submit the appropriate AccountCore revocation transaction through their normal wallet transaction flow.

Available methods

Method Purpose Testnet
account_core.authorize_account_signer_by_sig Grant the secondary EOA trading permission; can install its EIP-7702 delegation in the same transaction. Enabled
wallet.execute_batch Place readable native orders, cancel slots, or combine both. Enabled
wallet.execute_replace_by_slot_packed Place, replace, and cancel specific maker slots using compact 32-byte operations. Enabled
wallet.create_replace_trigger Register a conditional packed replacement. Disabled
wallet.create_batch_trigger Register a conditional native-order batch. Disabled
wallet.cancel_trigger Cancel an active trigger. Enabled

Trigger creation is part of the versioned API but is not routable on the current testnet deployment. See Conditional orders.

Request envelope

Every REST request has the same outer shape:

{
  "requestId": "018f5ef2-88a1-7b41-a826-4b679010f87f",
  "method": "wallet.execute_batch",
  "wallet": "0x1111111111111111111111111111111111111111",
  "payload": {},
  "authorization7702": null
}
Field Meaning
requestId A new lowercase UUIDv7 used for correlation. It is not durable idempotency.
method One exact method name from the table above.
wallet The secondary trading EOA. It must match the wallet claim in the JWT.
payload The method-specific signed fields.
authorization7702 null, except while installing or changing delegation as part of the same sponsored transaction.

All integer fields in JSON are unsigned decimal strings. Addresses and byte strings use exact-width 0x hexadecimal. Unknown and duplicate JSON fields are rejected.

Submit a completed request with:

curl --fail-with-body \
  --request POST \
  --url https://api.relay.testnet.kuru.io/relay \
  --header "Authorization: Bearer $KURU_RELAY_JWT" \
  --header "Content-Type: application/json" \
  --data @request.json

Responses

{
  "requestId": "018f5ef2-88a1-7b41-a826-4b679010f87f",
  "status": "BROADCAST",
  "txHash": "0x...",
  "sponsorAddress": "0x...",
  "sponsorNonce": "42",
  "transactionType": "DYNAMIC_FEE"
}

transactionType is SET_CODE when the request includes an accepted EIP-7702 authorization and DYNAMIC_FEE otherwise.

Read Responses and retries before implementing automatic retries. Use the OpenAPI YAML for the complete machine-readable schemas.