Pagination & Limits

Pagination & Limits

The API ships cursor-based pagination on every list endpoint. Per-endpoint batch caps and Solana protocol limits apply on top.

Cursor pagination

Every list endpoint accepts two query parameters:

ParamDefaultMaxNotes
limit20100How many items to return
cursorOpaque base64url token from the previous page's meta.next_cursor

The response wraps the list under data and adds three fields to meta:

GET /v2/pools?limit=2

{
  "data": [
    { "address": "POOL_A…", "type": "dbc",     "status": "live",      ... },
    { "address": "POOL_B…", "type": "damm_v2", "status": "migrated",  ... }
  ],
  "meta": {
    "request_id":  "req_01HXYZ…",
    "count":       2,
    "has_more":    true,
    "next_cursor": "eyJpZCI6Ijc3In0"
  }
}

Iterate by feeding meta.next_cursor into the next request:

curl "https://api.piratecrew.fun/v2/pools?limit=20&cursor=eyJpZCI6Ijc3In0" \
  -H "Authorization: Bearer $PIRATE_API_KEY"

When has_more is false, next_cursor is omitted — stop iterating. Cursors are opaque; do not parse, derive, or persist them long-term (they may be rotated when underlying storage changes).

List endpoints available: GET /v2/pools, GET /v2/airdrops, GET /v2/merkle-trees, GET /v2/stakes, GET /v2/nfts, GET /v2/gold-locks, GET /v2/tokens, GET /v2/webhook-subscriptions.

Endpoint batch caps

EndpointCapBehavior on overflow
POST /v2/accounts/batch-fetch100 addresses per call400 bad_request
POST /v2/merkle-trees50,000 entries per tree400 bad_request
POST /v2/transactions with bundle: true1–5 signed transactions per bundle400 bad_request
POST /v2/pools/{address}/fee-claims with kind: "split"2–10 recipients per split400 bad_request

The split route additionally requires splits[].bps values to sum to exactly 10000. Any other total is rejected with 400 bad_request — there is no implicit rounding or remainder routing.

Solana protocol limits

The Solana network caps a single transaction at 1232 bytes (1280-byte packet minus headers). Some transaction builders (notably fee-claim with kind: "split" and a large recipient list, and POST /v2/tokens with metadata) can push close to that ceiling once your wallet's account-lookup-table savings are factored in.

If a flow legitimately needs more than one transaction (e.g. pool create + first buy), build each transaction independently with mode=unsigned, sign all of them locally, and submit them atomically as a Jito bundle:

curl -X POST https://api.piratecrew.fun/v2/transactions \
  -H "Authorization: Bearer $PIRATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "bundle": true, "signed_transactions": ["<tx1>", "<tx2>"] }'

Either every transaction in the bundle lands in the same slot or none of them do.

Per-key rate limits

Each API key carries its own rate_limit_per_minute and rate_limit_per_day (configured in the Supabase api_keys table). Counters reset on a rolling window. Exceeding either ceiling returns 429:

{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests this minute"
  },
  "meta": { "request_id": "req_…" }
}

Retry with exponential backoff starting at one second. Do not retry any other 4xx code.

Request size

There is no documented hard ceiling on the JSON request body beyond Express's defaults, but practical limits emerge from the per-endpoint constraints above. A 50,000-entry merkle tree, for example, is the largest request you'd normally send — that's around 4 MB of JSON depending on entry shape.

No offset/limit pagination

The API has no ?offset=…&limit=… pagination. Use cursors on list endpoints, or fall back to batch reads:

  • Batch readPOST /v2/accounts/batch-fetch takes up to 100 explicit addresses per call. Chunk client-side if you need more.
  • Single-resource lookupGET /v2/pools/{address}, GET /v2/merkle-trees/{id}/proofs/{wallet}, GET /v2/tokens/{mint}, GET /v2/transactions/{signature}, etc.