Seller Endpoints

All seller endpoints require authentication via one of:

  • si_seller_ API key: Authorization: Bearer si_seller_xxx (programmatic access)
  • Privy session cookie (web UI)

A si_seller_ key cannot access buyer endpoints, and vice versa. Session cookies work for both.

Authentication — SIWE (Sign-In With Ethereum)

Get a seller API key using wallet signature auth. No browser needed.

Get Challenge

GET/v1/seller/auth/challenge

Returns a SIWE message with nonce and 5-minute expiry. The message must be signed and returned within 5 minutes. The server validates domain, uri, chainId, issuedAt (must be within ±5min of server time), and expirationTime (max 10min from issuedAt).

Get challenge
bash
GET /v1/seller/auth/challenge?address=0xYourWallet
json
{
  "message": "www.surplusintelligence.ai wants you to sign in...",
  "nonce": "abc123def456",
  "expires_at": 1713312000000
}

Issue Key

POST/v1/seller/auth/keys

Exchange the signed SIWE message for a seller API key. Save the returned key — it will not be shown again.

Issue key
bash
POST /v1/seller/auth/keys
{
  "message": "<SIWE message from challenge>",
  "signature": "0x...",
  "label": "my-bot",           // optional
  "expires_at": 1713398400000  // optional, ms timestamp
}
json
{
  "id": "uuid",
  "api_key": "si_seller_abc123def456...",
  "key_prefix": "si_seller_abc123de",
  "key_type": "seller",
  "wallet": "0xYourWallet",
  "expires_at": null,
  "created_at": 1713312000000,
  "message": "Save this API key — it will not be shown again."
}

Manage Keys

GET/v1/seller/keys

List keys. An existing seller key (or web session) authorizes this.

DELETE/v1/seller/keys/{keyId}

Revoke a key. An existing seller key (or web session) authorizes this.

Manage keys
bash
GET /v1/seller/keys
Authorization: Bearer si_seller_xxx
bash
DELETE /v1/seller/keys/{keyId}
Authorization: Bearer si_seller_xxx

Offers

POST/v1/seller/offers

Create offer.

PATCH/v1/seller/offers/{id}

Update price/caps.

DELETE/v1/seller/offers/{id}

Deactivate / soft-delete (encrypted key is retained; revoke at provider for immediate key invalidation).

GET/v1/seller/offers

List my offers.

There is no bulk-delete endpoint; remove offers one at a time with DELETE /v1/seller/offers/{id}.

Offers
bash
POST /v1/seller/offers
Authorization: Bearer si_seller_xxx
{
  "model": "claude-opus-4.6",
  "api_key": "your-provider-api-key",
  "seller_base_url": "https://api.venice.ai/api/v1",
  "price_input_per_1m": 12.00,
  "price_output_per_1m": 48.00,
  "cap_daily_usd": 100.00,
  "payout_address": "0xOptional..."
}
bash
PATCH /v1/seller/offers/{id}
Authorization: Bearer si_seller_xxx
{ "price_input_per_1m": 10.00 }
bash
DELETE /v1/seller/offers/{id}
Authorization: Bearer si_seller_xxx
bash
GET /v1/seller/offers
Authorization: Bearer si_seller_xxx

Bulk Create

POST/v1/seller/offers/bulk

Create multiple offers from discovery results.

Up to 200 offers per request. Bulk-created offers support the same cap_daily_usd field as single-offer creation.

Bulk create
bash
POST /v1/seller/offers/bulk
Authorization: Bearer si_seller_xxx
{
  "api_key": "your-provider-api-key",
  "base_url": "https://api.venice.ai/api/v1",
  "offers": [
    { "model": "claude-opus-4.6", "cost_multiplier": 0.5 },
    { "model": "gpt-5.4", "cost_multiplier": 0.5 }
  ]
}

Model Discovery

POST/v1/seller/discover

Auto-detect models + pricing from provider (no auth required).

Parses Venice, OpenRouter, Bankr, and generic pricing formats automatically.

Discover
bash
POST /v1/seller/discover
{ "api_key": "your-provider-api-key", "base_url": "https://api.venice.ai/api/v1" }

Test Connection

POST/v1/seller/test-connection

Verify endpoint is reachable and returns valid responses.

Test connection
bash
POST /v1/seller/test-connection
Authorization: Bearer si_seller_xxx
{ "api_key": "your-provider-api-key", "base_url": "https://api.venice.ai/api/v1", "model": "claude-opus-4.6" }

Earnings

GET/v1/seller/earnings

Returns: total earned, confirmed earned, total tokens served, recent transactions.

Query params: limit (default 50, max 100), offset (default 0).

Earnings
bash
GET /v1/seller/earnings
Authorization: Bearer si_seller_xxx

Health Log

GET/v1/seller/health-log

Returns: recent health events for your offers (failures, backoffs, recoveries).

Query params: offer_id (optional filter), limit (default 50, max 200).

Health log
bash
GET /v1/seller/health-log
Authorization: Bearer si_seller_xxx

Rate Limits

All seller endpoints are rate-limited per API key and per wallet:

Route ClassPer-Key LimitPer-Wallet Aggregate
Offers CRUD (GET/POST/PATCH/DELETE)30 req/min200 req/min
Bulk-create / Discover5 req/min200 req/min
Earnings / Health (read-only)60 req/min
Key management (issue/revoke)10 req/min per IP
Challenge (SIWE)20 req/min per IP

429 responses include Retry-After (seconds) and X-RateLimit-Reset (Unix timestamp) headers.

These route limits are API-abuse controls. They are not a marketplace-side spend ceiling for provider usage. For provider-quota protection, use cap_daily_usd and provider-side API-key limits where available. There is no per-week or per-month USD cap on marketplace seller offers today.

Key Storage and Deletion

Seller provider API keys are encrypted at rest with AES-256-GCM under AWS KMS envelope encryption: a per-secret data key is requested from KMS, used to encrypt the plaintext, and the ciphertext plus the KMS-encrypted data key are stored in a private S3 bucket. The server decrypts keys only when it needs to call the seller's provider endpoint or run seller-owned management actions such as discovery/test-connection/health reset.

Deleting an offer is currently a soft delete: active = false on the offer record, removed from routing, encrypted API key retained in storage. There is no self-serve hard-delete endpoint yet. Sellers should revoke deleted offer keys at their upstream provider if immediate invalidation is required.

See Security & Privacy for the full current trust model.

Error Responses

All errors follow the format:

json
{
  "error": {
    "message": "Human-readable description",
    "type": "authentication_error | authorization_error | invalid_request_error | rate_limit_error | server_error"
  }
}
StatusMeaning
400Invalid request (bad JSON, missing fields, unsupported model)
401Invalid or missing API key
403Wrong key type (e.g., buyer key on seller endpoint)
404Offer not found or doesn't belong to your wallet
429Rate limit exceeded
500Server error