{"openapi":"3.0.0","info":{"title":"PirateCrew Blockchain API (v2)","version":"2.0.0","description":"v2 of the PirateCrew Blockchain API. Noun-based REST resources, standard `{ data, meta }` response envelope, cursor pagination, polymorphic pool resource, lifecycle fields on every long-lived resource, and a canonical webhook event catalog.\n\nv1 remains available at `/v1` and is now deprecated.","contact":{"name":"PirateCrew","url":"https://piratecrew.fun"},"license":{"name":"ISC"}},"servers":[{"url":"https://api.piratecrew.fun","description":"Production"},{"url":"http://localhost:4000","description":"Local dev"}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"Supabase-issued API key. Stored in the `api_keys` table."}},"schemas":{"IdempotencyKey":{"type":"string","minLength":1,"maxLength":255,"description":"Client-supplied key (UUID v4 recommended) for safe write retries. Server stores `(key, request_hash, response)` and replays. Reusing with a different body returns 409 `idempotency_conflict`.","example":"9d3e2c8a-7f0b-4d44-9c3e-c4b1a4a4d0a8"},"RequestId":{"type":"string","minLength":1,"maxLength":128,"description":"Optional client-supplied request ID, echoed in `X-Request-Id` response header.","example":"req_a1b2c3d4e5f6"},"HealthPayload":{"type":"object","properties":{"status":{"type":"string","enum":["healthy"]},"timestamp":{"type":"string"},"service":{"type":"string"},"version":{"type":"string"}},"required":["status","timestamp","service","version"]},"Meta":{"type":"object","properties":{"request_id":{"type":"string","example":"req_a1b2c3d4e5f6"},"external_uid":{"type":"string"},"metadata":{"type":"object","additionalProperties":{"type":"string"}}},"required":["request_id"],"description":"Cross-cutting response metadata. `request_id` is always set; `external_uid` and `metadata` are echoed from the inbound request when present."},"HealthResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HealthPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"WorkerStatus":{"type":"object","properties":{"name":{"type":"string","description":"Stable identifier — one of `webhook-delivery`, `transaction-watcher`, `pool-migration`, `gold-unlock-eligible`, `airdrop-fully-claimed`."},"running":{"type":"boolean"},"last_tick_at":{"type":"string","nullable":true},"ticks_total":{"type":"integer","minimum":0},"errors_total":{"type":"integer","minimum":0},"last_error":{"type":"string","nullable":true},"last_error_at":{"type":"string","nullable":true}},"required":["name","running","last_tick_at","ticks_total","errors_total","last_error","last_error_at"]},"WorkersHealthPayload":{"type":"object","properties":{"all_healthy":{"type":"boolean","description":"True iff every worker is `running` AND has more successful ticks than errors. False is a hint to inspect individual entries; not a hard outage signal."},"observed_at":{"type":"string"},"workers":{"type":"array","items":{"$ref":"#/components/schemas/WorkerStatus"}}},"required":["all_healthy","observed_at","workers"]},"WorkersHealthResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkersHealthPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"ApiError":{"type":"object","properties":{"code":{"type":"string","example":"pool_not_found"},"message":{"type":"string","example":"No pool exists at address 7xKX..."},"param":{"type":"string","example":"address"},"details":{"type":"string"},"doc_url":{"type":"string","format":"uri"}},"required":["code","message"]},"ApiErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ApiError"},"meta":{"type":"object","properties":{"request_id":{"type":"string","example":"req_a1b2c3d4e5f6"}},"required":["request_id"]}},"required":["error","meta"]},"PoolLifecycle":{"type":"string","enum":["pending","live","migration_triggered","migrated","failed"],"description":"Lifecycle state of a Pool. See https://docs.piratecrew.fun/concepts/lifecycles for the state machine."},"Pool":{"type":"object","properties":{"type":{"type":"string","enum":["dbc","damm_v2"],"description":"Pool family. `dbc` = Meteora Dynamic Bonding Curve (launch). `damm_v2` = Meteora CP-AMM (post-migration)."},"address":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"base_mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"quote_mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"config":{"type":"string","nullable":true,"pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"creator":{"type":"string","nullable":true,"pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"name":{"type":"string","nullable":true},"symbol":{"type":"string","nullable":true},"metadata_uri":{"type":"string","nullable":true,"format":"uri"},"status":{"$ref":"#/components/schemas/PoolLifecycle"},"curve_progress":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Fraction of bonding-curve migration threshold reached (0–1). `null` for `damm_v2` pools."},"state":{"nullable":true,"description":"Raw on-chain state object from the underlying SDK."},"fee_metrics":{"nullable":true},"created_at":{"type":"string","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":{"type":"string"}}},"required":["type","address","base_mint","quote_mint","config","creator","name","symbol","metadata_uri","status","curve_progress","created_at","metadata"]},"ListMeta":{"allOf":[{"$ref":"#/components/schemas/Meta"},{"type":"object","properties":{"has_more":{"type":"boolean","description":"True if more pages exist beyond `next_cursor`."},"next_cursor":{"type":"string","nullable":true,"description":"Opaque cursor to pass back as `?cursor=…` for the next page. `null` when `has_more` is false."},"count":{"type":"integer","minimum":0,"description":"Number of items in this page."}},"required":["has_more","next_cursor","count"]}],"description":"Cross-cutting response metadata. `request_id` is always set; `external_uid` and `metadata` are echoed from the inbound request when present."},"PoolListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Pool"}},"meta":{"$ref":"#/components/schemas/ListMeta"}},"required":["data","meta"]},"PoolCreatedPayload":{"type":"object","properties":{"pool":{"$ref":"#/components/schemas/Pool"},"transactions":{"type":"array","items":{"type":"string"},"description":"base64-encoded VersionedTransaction blobs for the client to sign."},"required_signers":{"type":"object","properties":{"base_mint_secret_key":{"type":"array","items":{"type":"integer"}},"config_secret_key":{"type":"array","items":{"type":"integer"}}},"required":["base_mint_secret_key","config_secret_key"]},"jito_tip_account":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"rpc_endpoint":{"type":"string","format":"uri"}},"required":["pool","transactions","required_signers","jito_tip_account","rpc_endpoint"]},"PoolCreatedResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PoolCreatedPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"PoolCreateRequest":{"type":"object","properties":{"type":{"type":"string","enum":["dbc","damm_v2"],"default":"dbc","description":"Pool family. `dbc` = Meteora Dynamic Bonding Curve (launch). `damm_v2` = Meteora CP-AMM (post-migration)."},"creator":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"name":{"type":"string","pattern":"^[a-zA-Z0-9 ]{1,20}$"},"symbol":{"type":"string","pattern":"^[A-Za-z0-9]{1,10}$"},"description":{"type":"string","maxLength":500},"image":{},"buy_amount":{"type":"number","minimum":0,"default":0},"website":{"type":"string","format":"uri"},"twitter_url":{"type":"string","format":"uri"},"telegram":{"type":"string","format":"uri"},"loot_from":{"type":"string","maxLength":100},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["creator","name","symbol","image"]},"PoolResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Pool"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"PoolVerificationPayload":{"type":"object","properties":{"pool":{"$ref":"#/components/schemas/Pool"},"verified":{"type":"boolean"}},"required":["pool","verified"]},"PoolVerificationResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PoolVerificationPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"PoolVerificationRequest":{"type":"object","properties":{"transactions":{"type":"array","items":{"type":"string"},"description":"Optional signed bundle to submit before marking live (legacy flow)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}}},"CurveProgressPayload":{"type":"object","properties":{"pool_address":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"progress":{"type":"number","minimum":0,"maximum":1},"migration_market_cap_usd":{"type":"number"}},"required":["pool_address","progress"]},"CurveProgressResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CurveProgressPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"PoolFeeMetricsPayload":{"type":"object","properties":{"pool_address":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"partner_quote_fee":{"type":"string","pattern":"^\\d+$","description":"Token/lamport amounts as decimal strings (u64-safe; can exceed JS Number.MAX_SAFE_INTEGER).","example":"1000000000"},"partner_base_fee":{"type":"string","pattern":"^\\d+$","description":"Token/lamport amounts as decimal strings (u64-safe; can exceed JS Number.MAX_SAFE_INTEGER).","example":"1000000000"},"surplus_status":{"type":"string","enum":["available","withdrawn","unknown"]},"raw":{"nullable":true}},"required":["pool_address","partner_quote_fee","surplus_status"]},"PoolFeeMetricsResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PoolFeeMetricsPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"UnsignedTxPayload":{"type":"object","properties":{"mode":{"type":"string","enum":["unsigned"]},"transaction":{"type":"string","description":"base64 VersionedTransaction"},"requiredSigners":{"type":"array","items":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}}},"required":["mode","transaction"]},"SignedTxPayload":{"type":"object","properties":{"mode":{"type":"string","enum":["signed"]},"signature":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{43,90}$"}},"required":["mode","signature"]},"FeeClaimPayload":{"type":"object","properties":{"pool_address":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"kind":{"type":"string","enum":["dbc","damm_v2","surplus"],"description":"`dbc` = claim partner fees from a DBC pool; `damm_v2` = claim fees from the post-migration DAMM v2 pool; `surplus` = withdraw post-migration surplus."},"estimated_quote":{"type":"string","pattern":"^\\d+$","description":"Token/lamport amounts as decimal strings (u64-safe; can exceed JS Number.MAX_SAFE_INTEGER).","example":"1000000000"},"tx":{"anyOf":[{"$ref":"#/components/schemas/UnsignedTxPayload"},{"$ref":"#/components/schemas/SignedTxPayload"}]}},"required":["pool_address","kind","tx"]},"FeeClaimResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/FeeClaimPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"FeeSplitEntry":{"type":"object","properties":{"recipient":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"bps":{"type":"integer","minimum":1,"maximum":10000}},"required":["recipient","bps"]},"FeeClaimCreateRequest":{"type":"object","properties":{"kind":{"type":"string","enum":["dbc","damm_v2","surplus"],"default":"dbc","description":"`dbc` = claim partner fees from a DBC pool; `damm_v2` = claim fees from the post-migration DAMM v2 pool; `surplus` = withdraw post-migration surplus."},"payer":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Wallet that pays tx fees. In `mode=signed` this is informational; the platform wallet actually pays.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"splits":{"type":"array","items":{"$ref":"#/components/schemas/FeeSplitEntry"},"minItems":2,"maxItems":10,"description":"If provided, atomically claim AND split the partner fees in one tx. Sum of `bps` must = 10000. Only valid for `kind: \"dbc\"`. Omit for a plain claim."},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["payer"]},"FeeClaimHistoryEntry":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["fee_claim.executed","fee_claim.split_executed"]},"pool_address":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"signature":{"type":"string","nullable":true,"pattern":"^[1-9A-HJ-NP-Za-km-z]{43,90}$"},"occurred_at":{"type":"string"},"external_uid":{"type":"string","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":{"type":"string"}}},"required":["id","type","pool_address","signature","occurred_at","external_uid","metadata"]},"FeeClaimHistoryResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FeeClaimHistoryEntry"}},"meta":{"$ref":"#/components/schemas/ListMeta"}},"required":["data","meta"]},"AirdropLifecycle":{"type":"string","enum":["tree_built","initialized","claiming","fully_claimed","vault_drained"],"description":"Lifecycle defaults to `tree_built` whenever a `merkle_trees` row exists. We do not currently track on-chain init/claim/drain state server-side, so progression past `tree_built` requires a future tx-watcher."},"Airdrop":{"type":"object","properties":{"id":{"type":"string","description":"Opaque base64url-encoded composite identifier of `mint:airdrop_count`. Same shape as the merkle-tree id — an airdrop is the on-chain manifestation of a stored merkle tree.","example":"N3hLWHRnMkNXODdkOTdUWEpTRHBiRDVqQmtoZVRxQTgzVFpSdUpvc2dBc1U6MA"},"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"airdrop_count":{"type":"integer","minimum":0,"maximum":65535},"root":{"type":"string","description":"Hex-encoded 32-byte merkle root (no `0x` prefix)."},"leaf_count":{"type":"integer","minimum":0},"status":{"$ref":"#/components/schemas/AirdropLifecycle"},"created_at":{"type":"string","nullable":true}},"required":["id","mint","airdrop_count","root","leaf_count","status","created_at"]},"AirdropListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Airdrop"}},"meta":{"$ref":"#/components/schemas/ListMeta"}},"required":["data","meta"]},"TxModePayload":{"anyOf":[{"$ref":"#/components/schemas/UnsignedTxPayload"},{"$ref":"#/components/schemas/SignedTxPayload"}]},"AirdropCreatedResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TxModePayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"AirdropCreateRequest":{"type":"object","properties":{"payer":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_id":{"type":"string","minLength":1,"maxLength":64},"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"airdrop_count":{"type":"integer","minimum":0,"maximum":65535},"merkle_root":{"type":"string","description":"32-byte merkle root, hex (with or without `0x` prefix)."},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["payer","platform_id","mint","airdrop_count","merkle_root"]},"AirdropResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Airdrop"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"TrackedResourceHint":{"type":"object","properties":{"resource_type":{"type":"string","enum":["airdrop"]},"resource_id":{"type":"string"},"related_events":{"type":"array","items":{"type":"string","enum":["airdrop.claimed"]}}},"required":["resource_type","resource_id","related_events"],"description":"Echo this object verbatim as `tracked_resource` on the subsequent `POST /v2/transactions` submit."},"AirdropClaimPayload":{"allOf":[{"$ref":"#/components/schemas/UnsignedTxPayload"},{"type":"object","properties":{"swap_transaction":{"type":"string","nullable":true,"description":"Optional base64 Jupiter swap-to-SOL transaction when `swap_to_sol` was true."},"tracked_resource":{"$ref":"#/components/schemas/TrackedResourceHint"}},"required":["swap_transaction","tracked_resource"]}]},"AirdropClaimResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AirdropClaimPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"AirdropClaimRequest":{"type":"object","properties":{"claimer":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_id":{"type":"string","minLength":1,"maxLength":64},"amount":{"anyOf":[{"type":"string"},{"type":"number"}],"description":"Raw u64 amount to claim (decimal string). When `proof` is omitted the amount + proof are looked up from the stored merkle tree and this field is ignored."},"proof":{"type":"array","items":{"type":"string"},"description":"Provide directly, or omit to fetch from the server-stored merkle tree referenced by `{id}`."},"platform_fee":{"type":"integer","minimum":0,"default":0,"description":"Platform fee in lamports, paid by the claimer."},"swap_to_sol":{"type":"boolean","default":false,"description":"If true, the response includes an auxiliary Jupiter swap-to-SOL transaction the client can submit alongside the claim."},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"Always returns an unsigned transaction — `mode: signed` is rejected because the claimer wallet must sign."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["claimer","platform_id","amount"]},"AirdropVaultWithdrawalPayload":{"allOf":[{"$ref":"#/components/schemas/SignedTxPayload"},{"type":"object","properties":{"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"amount":{"type":"string","pattern":"^\\d+$","description":"Token/lamport amounts as decimal strings (u64-safe; can exceed JS Number.MAX_SAFE_INTEGER).","example":"1000000000"}},"required":["mint","amount"]}]},"AirdropVaultWithdrawalResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AirdropVaultWithdrawalPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"AirdropVaultWithdrawalRequest":{"type":"object","properties":{"admin":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Defaults to the platform wallet derived server-side.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"amount":{"type":"string","pattern":"^\\d+$","description":"Token/lamport amounts as decimal strings (u64-safe; can exceed JS Number.MAX_SAFE_INTEGER).","example":"1000000000"},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["amount"]},"MerkleTree":{"type":"object","properties":{"id":{"type":"string","description":"Opaque base64url-encoded composite identifier of `mint:airdrop_count`. Use to look up proofs and to reference the tree from the airdrops API.","example":"N3hLWHRnMkNXODdkOTdUWEpTRHBiRDVqQmtoZVRxQTgzVFpSdUpvc2dBc1U6MA"},"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"airdrop_count":{"type":"integer","minimum":0,"maximum":65535},"root":{"type":"string","description":"Hex-encoded 32-byte merkle root (no `0x` prefix).","example":"ab12..."},"root_hex":{"type":"string","description":"Hex-encoded 32-byte merkle root with `0x` prefix.","example":"0xab12..."},"leaf_count":{"type":"integer","minimum":0},"persisted":{"type":"boolean","description":"True if the tree was stored server-side and proofs are retrievable via `GET /v2/merkle-trees/{id}/proofs/{wallet}`."}},"required":["id","mint","airdrop_count","root","root_hex","leaf_count","persisted"]},"MerkleTreeResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MerkleTree"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"MerkleEntry":{"type":"object","properties":{"wallet":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"amount":{"anyOf":[{"type":"string"},{"type":"number"}],"description":"Either a u64 decimal string (raw on-chain units) or a JS number (multiplied by 10^decimals when `decimals` is provided in the request).","example":"1000000"}},"required":["wallet","amount"]},"MerkleTreeCreateRequest":{"type":"object","properties":{"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"airdrop_count":{"type":"integer","minimum":0,"maximum":65535,"default":0,"description":"Discriminator (0–65535) so multiple distinct airdrops can share a mint without colliding in storage."},"decimals":{"type":"integer","minimum":0,"maximum":18,"description":"If present, numeric `entries[].amount` values are scaled by 10^decimals. Omit when amounts are already raw u64 strings."},"entries":{"type":"array","items":{"$ref":"#/components/schemas/MerkleEntry"},"minItems":1,"maxItems":50000},"persist":{"type":"boolean","default":true,"description":"Persist the tree in the `merkle_trees` table so proofs can be fetched later via `GET /v2/merkle-trees/{id}/proofs/{wallet}`."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["mint","entries"]},"MerkleProof":{"type":"object","properties":{"wallet":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"amount":{"type":"string","pattern":"^\\d+$","description":"Token/lamport amounts as decimal strings (u64-safe; can exceed JS Number.MAX_SAFE_INTEGER).","example":"1000000000"},"root":{"type":"string","description":"Hex-encoded 32-byte merkle root (no prefix)."},"proof":{"type":"array","items":{"type":"string"},"description":"Sibling hashes from leaf to root, hex-encoded (no prefix)."}},"required":["wallet","mint","amount","root","proof"]},"MerkleProofResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MerkleProof"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"StakeTxResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TxModePayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"StakeCreateRequest":{"type":"object","properties":{"user":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"User wallet acquiring the stake; signs the returned tx.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_id":{"type":"string","minLength":1,"maxLength":64},"asset":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"NFT asset address (mpl-core).","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"collection":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_fee":{"type":"integer","minimum":0,"default":0,"description":"Platform fee in lamports applied at stake time."},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["user","platform_id","asset","collection"]},"StakeReleaseRequest":{"type":"object","properties":{"user":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"User wallet releasing the stake; signs the returned tx.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_id":{"type":"string","minLength":1,"maxLength":64},"collection":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_fee":{"type":"integer","minimum":0,"default":0},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["user","platform_id","collection"]},"StakeLifecycle":{"type":"string","enum":["unstaked","staked","burned"],"description":"Lifecycle state of a Stake. See https://docs.piratecrew.fun/concepts/lifecycles for the state machine."},"Stake":{"type":"object","properties":{"asset":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"collection":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"owner":{"type":"string","nullable":true,"pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"status":{"$ref":"#/components/schemas/StakeLifecycle"},"platform_id":{"type":"string","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":{"type":"string"}}},"required":["asset","collection","owner","status","platform_id","metadata"]},"StakeLookupPayload":{"type":"object","properties":{"wallet":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"note":{"type":"string","description":"Stake state is encoded on the mpl-core asset plugin; fetch /v2/accounts/{asset} and decode the plugin layer client-side."},"staked_assets":{"type":"array","items":{"$ref":"#/components/schemas/Stake"}}},"required":["wallet","note","staked_assets"]},"StakeLookupResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/StakeLookupPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"NftTxResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TxModePayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"NftMintRequest":{"type":"object","properties":{"payer":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Wallet paying for and receiving the mint; signs the returned tx.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_id":{"type":"string","minLength":1,"maxLength":64},"collection":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"name":{"type":"string","minLength":1,"maxLength":64},"uri":{"type":"string","format":"uri","description":"Off-chain metadata URI."},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["payer","platform_id","collection","name","uri"]},"NftBurnRequest":{"type":"object","properties":{"owner":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Owner of the asset; signs the returned tx.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_id":{"type":"string","minLength":1,"maxLength":64},"collection":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["owner","platform_id","collection"]},"GoldLockTxResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TxModePayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"GoldLockCreateRequest":{"type":"object","properties":{"user":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"User wallet locking GOLD; signs the returned tx.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_id":{"type":"string","minLength":1,"maxLength":64},"amount":{"type":"string","pattern":"^\\d+$","description":"Amount of GOLD to lock, as a u64-safe decimal string.","example":"1000000000"},"lock_duration_days":{"type":"integer","minimum":1,"maximum":1460,"description":"Lock duration in whole days (1–1460)."},"platform_fee":{"type":"integer","minimum":0,"default":0},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["user","platform_id","amount","lock_duration_days"]},"GoldLockReleaseRequest":{"type":"object","properties":{"platform_id":{"type":"string","minLength":1,"maxLength":64},"platform_fee":{"type":"integer","minimum":0,"default":0},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["platform_id"]},"TokenCreatedPayload":{"type":"object","properties":{"mode":{"type":"string","enum":["unsigned"]},"transaction":{"type":"string","description":"base64-encoded VersionedTransaction for the client to sign."},"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"required_signers":{"type":"object","properties":{"mint_secret_key":{"type":"array","items":{"type":"integer"},"description":"Secret key bytes for the freshly generated mint Keypair. Client must include this signer when submitting the tx."}},"required":["mint_secret_key"]}},"required":["mode","transaction","mint","required_signers"]},"TokenCreatedResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TokenCreatedPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"TokenCreateRequest":{"type":"object","properties":{"payer":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"name":{"type":"string","minLength":1,"maxLength":32},"symbol":{"type":"string","minLength":1,"maxLength":10},"decimals":{"type":"integer","minimum":0,"maximum":9,"default":6},"initial_supply":{"type":"string","pattern":"^\\d+$","description":"Token/lamport amounts as decimal strings (u64-safe; can exceed JS Number.MAX_SAFE_INTEGER).","example":"1000000000"},"uri":{"type":"string","format":"uri"},"revoke_mint_authority":{"type":"boolean","default":false},"revoke_freeze_authority":{"type":"boolean","default":true},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["payer","name","symbol","initial_supply","uri"]},"TokenRevokeAuthorityResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TxModePayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"TokenRevokeAuthorityRequest":{"type":"object","properties":{"payer":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"mode":{"type":"string","enum":["unsigned","signed"],"default":"unsigned","description":"`unsigned` returns a base64 VersionedTransaction the client signs; `signed` has the server sign + submit via Privy (requires the relevant `*:signed` scope)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["payer"]},"TokenLifecycle":{"type":"string","enum":["created","mint_authority_revoked","freeze_authority_revoked","fully_immutable"],"description":"Lifecycle state of a Token. See https://docs.piratecrew.fun/concepts/lifecycles for the state machine."},"Token":{"type":"object","properties":{"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"status":{"$ref":"#/components/schemas/TokenLifecycle"},"raw":{"nullable":true,"description":"Raw response from the upstream metadata provider (Helius `getAsset`). Shape is vendor-defined and may evolve."}},"required":["mint","status"]},"TokenResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Token"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"TransactionSubmitPayload":{"type":"object","properties":{"signature":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{43,90}$","description":"Set when a single transaction was submitted (non-bundle)."},"bundle_id":{"type":"string","description":"Set when a Jito bundle was submitted; this is the bundle UUID Jito returns."},"signatures":{"type":"array","items":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{43,90}$"},"description":"Set when a Jito bundle was submitted. Currently echoes `[bundle_id]` until per-bundle tx signatures are surfaced."}}},"TransactionSubmitResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TransactionSubmitPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"TransactionSubmitRequest":{"type":"object","properties":{"transaction":{"type":"string","description":"base64-encoded signed VersionedTransaction. Required when `bundle` is `false`/omitted."},"signed_transactions":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":5,"description":"1–5 base64-encoded signed VersionedTransactions to submit as a single Jito bundle. Required when `bundle` is `true`."},"bundle":{"type":"boolean","default":false,"description":"If `true`, treat the request as a Jito bundle submission and require `signed_transactions`. If `false`/omitted, treat as a standard single-tx submit and require `transaction`."},"skip_preflight":{"type":"boolean","default":false},"max_retries":{"type":"integer","minimum":0,"maximum":10,"default":2},"tracked_resource":{"type":"object","properties":{"resource_type":{"type":"string","minLength":1,"maxLength":64},"resource_id":{"type":"string","minLength":1,"maxLength":256},"related_events":{"type":"array","items":{"type":"string","enum":["pool.created","pool.live","pool.migration_triggered","pool.migrated","pool.failed","airdrop.tree_built","airdrop.initialized","airdrop.claim_started","airdrop.claimed","airdrop.fully_claimed","airdrop.vault_drained","stake.acquired","stake.released","gold.locked","gold.unlock_eligible","gold.unlocked","nft.created","nft.staked","nft.unstaked","nft.burned","token.created","token.mint_authority_revoked","token.freeze_authority_revoked","token.fully_immutable","transaction.submitted","transaction.confirmed","transaction.finalized","transaction.failed","fee_claim.executed","fee_claim.split_executed","webhook.test_event"]},"maxItems":5,"default":[]}},"required":["resource_type","resource_id"],"description":"Optional. Tell the tx-watcher which resource this transaction relates to. On `confirmed` it will additionally emit each `related_events` (e.g. `pool.live`, `stake.acquired`)."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}}},"TransactionLifecycle":{"type":"string","enum":["unknown","submitted","processing","confirmed","finalized","failed"],"description":"Lifecycle state of a Transaction. See https://docs.piratecrew.fun/concepts/lifecycles for the state machine."},"Transaction":{"type":"object","properties":{"signature":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{43,90}$"},"lifecycle":{"$ref":"#/components/schemas/TransactionLifecycle"},"confirmation_status":{"type":"string","nullable":true,"enum":["processed","confirmed","finalized"],"description":"Raw Solana commitment level from `getSignatureStatuses`. Prefer `lifecycle` for client logic."},"err":{"nullable":true},"slot":{"type":"integer","nullable":true},"confirmations":{"type":"integer","nullable":true}},"required":["signature","lifecycle","confirmation_status","slot","confirmations"]},"TransactionResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Transaction"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"TransactionSimulationPayload":{"type":"object","properties":{"raw":{"nullable":true,"description":"Raw Solana RPC `simulateTransaction` result (`{ err, logs, accounts, unitsConsumed, ... }`). Shape follows web3.js verbatim."}}},"TransactionSimulationResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TransactionSimulationPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"TransactionSimulationRequest":{"type":"object","properties":{"transaction":{"type":"string","description":"base64-encoded VersionedTransaction to simulate."},"sig_verify":{"type":"boolean","default":false,"description":"If `true`, signature verification runs against the recent blockhash on the tx. If `false`, the simulator swaps in a fresh blockhash before running."}},"required":["transaction"]},"SwapQuotePayload":{"type":"object","properties":{"quote":{"nullable":true,"description":"Raw Jupiter `/quote` response (`{ inputMint, outputMint, inAmount, outAmount, otherAmountThreshold, slippageBps, routePlan, ... }`)."}}},"SwapQuoteResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SwapQuotePayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"SwapQuoteRequest":{"type":"object","properties":{"input_mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"output_mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"amount":{"type":"string","pattern":"^\\d+$","description":"Token/lamport amounts as decimal strings (u64-safe; can exceed JS Number.MAX_SAFE_INTEGER).","example":"1000000000"},"slippage_bps":{"type":"integer","minimum":0,"maximum":10000,"default":50,"description":"Max slippage in basis points (1 bps = 0.01%). Default 50 (0.5%)."},"swap_mode":{"type":"string","enum":["ExactIn","ExactOut"],"default":"ExactIn"}},"required":["input_mint","output_mint","amount"]},"SwapPayload":{"type":"object","properties":{"swap_transaction":{"type":"string","description":"base64 VersionedTransaction (legacy if `as_legacy_transaction` was true) ready for the user to sign and submit."},"last_valid_block_height":{"type":"integer"}},"required":["swap_transaction"]},"SwapResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SwapPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"SwapBuildRequest":{"type":"object","properties":{"user_public_key":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"quote_response":{"nullable":true,"description":"The exact `quote` object returned by `POST /v2/swap-quotes` (or Jupiter's `/quote` endpoint). Passed through to Jupiter `/swap` unchanged."},"wrap_and_unwrap_sol":{"type":"boolean","default":true},"as_legacy_transaction":{"type":"boolean","default":false},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["user_public_key"]},"Pda":{"type":"object","properties":{"name":{"type":"string","enum":["platform","treasury","airdrop_config","claim_airdrop","user_nft_config","gold_lock_config","user_lock_config","gold_vault","ve_gold_mint","user_ve_gold"],"description":"Canonical PDA name. Mirrors the derivation functions on the Pirates staking program."},"address":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"The derived program-derived address.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"bump":{"type":"integer","minimum":0,"maximum":255,"description":"Canonical PDA bump seed (0–255)."},"seeds_args":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"}]},"description":"Echo of the seed args used for derivation, in the same shape as the request body."}},"required":["name","address","bump","seeds_args"]},"PdaResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Pda"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"PlatformPdaRequest":{"type":"object","properties":{"platform_id":{"type":"string","minLength":1,"maxLength":64,"description":"UTF-8 identifier used as the second seed.","example":"main"}},"required":["platform_id"]},"TreasuryPdaRequest":{"type":"object","properties":{"platform_state":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Platform-state account address; included as a seed.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}},"required":["platform_state"]},"AirdropConfigPdaRequest":{"type":"object","properties":{"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"SPL mint the airdrop pays out.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"airdrop_count":{"type":"integer","minimum":0,"maximum":65535,"description":"u16 sequence number for the airdrop config; encoded little-endian."}},"required":["mint","airdrop_count"]},"ClaimAirdropPdaRequest":{"type":"object","properties":{"mint":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"user":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Recipient wallet.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"airdrop_config":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Address of the parent airdrop-config PDA.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}},"required":["mint","user","airdrop_config"]},"UserNftConfigPdaRequest":{"type":"object","properties":{"user":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}},"required":["user"]},"GoldLockConfigPdaRequest":{"type":"object","properties":{"platform_state":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}},"required":["platform_state"]},"UserLockConfigPdaRequest":{"type":"object","properties":{"user":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_state":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}},"required":["user","platform_state"]},"GoldVaultPdaRequest":{"type":"object","properties":{"platform_state":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}},"required":["platform_state"]},"VeGoldMintPdaRequest":{"type":"object","properties":{"platform_state":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}},"required":["platform_state"]},"UserVeGoldPdaRequest":{"type":"object","properties":{"user":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"platform_state":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"}},"required":["user","platform_state"]},"Account":{"type":"object","properties":{"address":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"exists":{"type":"boolean","description":"False when the address has never been initialized on-chain."},"lamports":{"type":"string","nullable":true,"pattern":"^\\d+$","description":"Account balance in lamports as a decimal string (u64-safe). `null` when `exists` is false.","example":"1000000000"},"owner":{"type":"string","nullable":true,"pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Owning program address. `null` when `exists` is false.","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"executable":{"type":"boolean","nullable":true},"rent_epoch":{"type":"number","nullable":true,"description":"Epoch at which the account next owes rent."},"data_len":{"type":"integer","nullable":true,"minimum":0,"description":"Byte length of the account data buffer."},"data_base64":{"type":"string","nullable":true,"description":"Base64-encoded account data. `null` when `exists` is false."}},"required":["address","exists","lamports","owner","executable","rent_epoch","data_len","data_base64"]},"AccountResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Account"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"AccountBatchFetchPayload":{"type":"object","properties":{"accounts":{"type":"array","items":{"$ref":"#/components/schemas/Account"},"description":"Results in the same order as the request `addresses` array."}},"required":["accounts"]},"AccountBatchFetchResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AccountBatchFetchPayload"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"AccountBatchFetchRequest":{"type":"object","properties":{"addresses":{"type":"array","items":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","example":"7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},"minItems":1,"maxItems":100,"description":"1–100 addresses to fetch in a single RPC round-trip."},"externalUid":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_\\-.:]+$","description":"Optional client-supplied identifier echoed on the response. Prefer `metadata` for richer reconciliation.","example":"campaign_2026_q2_airdrop_42"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["addresses"]},"EventCatalogEntry":{"type":"object","properties":{"type":{"type":"string","enum":["pool.created","pool.live","pool.migration_triggered","pool.migrated","pool.failed","airdrop.tree_built","airdrop.initialized","airdrop.claim_started","airdrop.claimed","airdrop.fully_claimed","airdrop.vault_drained","stake.acquired","stake.released","gold.locked","gold.unlock_eligible","gold.unlocked","nft.created","nft.staked","nft.unstaked","nft.burned","token.created","token.mint_authority_revoked","token.freeze_authority_revoked","token.fully_immutable","transaction.submitted","transaction.confirmed","transaction.finalized","transaction.failed","fee_claim.executed","fee_claim.split_executed","webhook.test_event"],"description":"One of the canonical event types."},"resource":{"type":"string"},"detection":{"type":"string","enum":["synchronous","tx_confirmed","polling_required"],"description":"`synchronous` = fires immediately from our route handler. `tx_confirmed` = fires after the user-signed tx finalizes on-chain (requires the tx-watcher to be online). `polling_required` = needs background polling we have not yet shipped."},"description":{"type":"string"}},"required":["type","resource","detection","description"]},"EventCatalogResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EventCatalogEntry"}},"meta":{"$ref":"#/components/schemas/ListMeta"}},"required":["data","meta"]},"WebhookSubscription":{"type":"object","properties":{"id":{"type":"string","example":"whsub_a1b2c3d4"},"url":{"type":"string","format":"uri"},"enabled_events":{"type":"array","items":{"anyOf":[{"type":"string","enum":["pool.created","pool.live","pool.migration_triggered","pool.migrated","pool.failed","airdrop.tree_built","airdrop.initialized","airdrop.claim_started","airdrop.claimed","airdrop.fully_claimed","airdrop.vault_drained","stake.acquired","stake.released","gold.locked","gold.unlock_eligible","gold.unlocked","nft.created","nft.staked","nft.unstaked","nft.burned","token.created","token.mint_authority_revoked","token.freeze_authority_revoked","token.fully_immutable","transaction.submitted","transaction.confirmed","transaction.finalized","transaction.failed","fee_claim.executed","fee_claim.split_executed","webhook.test_event"],"description":"One of the canonical event types."},{"type":"string","enum":["*"]}],"description":"Either a specific event type or the wildcard `*` to subscribe to everything."}},"active":{"type":"boolean"},"description":{"type":"string","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":{"type":"string"}},"created_at":{"type":"string"},"secret_preview":{"type":"string","description":"Last 4 characters of the signing secret, prefixed (e.g. `whsec_…wXyZ`). The full secret is only returned once at create time."}},"required":["id","url","enabled_events","active","description","metadata","created_at","secret_preview"]},"WebhookSubscriptionListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookSubscription"}},"meta":{"$ref":"#/components/schemas/ListMeta"}},"required":["data","meta"]},"WebhookSubscriptionWithSecret":{"allOf":[{"$ref":"#/components/schemas/WebhookSubscription"},{"type":"object","properties":{"secret":{"type":"string","description":"Full signing secret — store this securely. **Only returned once** at create time.","example":"whsec_d3a0d9c7b8e5f4a1c2b3d4e5f6a7b8c9"}},"required":["secret"]}]},"WebhookSubscriptionWithSecretResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookSubscriptionWithSecret"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"WebhookSubscriptionCreateRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"enabled_events":{"type":"array","items":{"anyOf":[{"type":"string","enum":["pool.created","pool.live","pool.migration_triggered","pool.migrated","pool.failed","airdrop.tree_built","airdrop.initialized","airdrop.claim_started","airdrop.claimed","airdrop.fully_claimed","airdrop.vault_drained","stake.acquired","stake.released","gold.locked","gold.unlock_eligible","gold.unlocked","nft.created","nft.staked","nft.unstaked","nft.burned","token.created","token.mint_authority_revoked","token.freeze_authority_revoked","token.fully_immutable","transaction.submitted","transaction.confirmed","transaction.finalized","transaction.failed","fee_claim.executed","fee_claim.split_executed","webhook.test_event"],"description":"One of the canonical event types."},{"type":"string","enum":["*"]}],"description":"Either a specific event type or the wildcard `*` to subscribe to everything."},"minItems":1,"default":["*"]},"description":{"type":"string","maxLength":500},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}},"required":["url"]},"WebhookSubscriptionResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookSubscription"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"WebhookSubscriptionUpdateRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"enabled_events":{"type":"array","items":{"anyOf":[{"type":"string","enum":["pool.created","pool.live","pool.migration_triggered","pool.migrated","pool.failed","airdrop.tree_built","airdrop.initialized","airdrop.claim_started","airdrop.claimed","airdrop.fully_claimed","airdrop.vault_drained","stake.acquired","stake.released","gold.locked","gold.unlock_eligible","gold.unlocked","nft.created","nft.staked","nft.unstaked","nft.burned","token.created","token.mint_authority_revoked","token.freeze_authority_revoked","token.fully_immutable","transaction.submitted","transaction.confirmed","transaction.finalized","transaction.failed","fee_claim.executed","fee_claim.split_executed","webhook.test_event"],"description":"One of the canonical event types."},{"type":"string","enum":["*"]}],"description":"Either a specific event type or the wildcard `*` to subscribe to everything."},"minItems":1},"active":{"type":"boolean"},"description":{"type":"string","nullable":true,"maxLength":500},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"description":"Free-form string key/value bag echoed back on responses and webhook events.","example":{"campaign":"q2_2026","ledger_id":"tx_abc123"}}}}},"parameters":{"IdempotencyKey":{"schema":{"$ref":"#/components/schemas/IdempotencyKey"},"required":false,"name":"Idempotency-Key","in":"header"},"RequestId":{"schema":{"$ref":"#/components/schemas/RequestId"},"required":false,"name":"X-Request-Id","in":"header"}}},"paths":{"/v2/health":{"get":{"summary":"Liveness probe (unauthed)","description":"Returns 200 with `status: \"healthy\"` whenever the process is up and the Express app is serving. Used by the Fly.io health check (`fly.toml`).","tags":["meta"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"}]}},"/v2/health/workers":{"get":{"summary":"Per-worker tick + error counters","description":"Snapshot of every background worker / poller's process-local metrics. Reset to zero on process restart — for persistent telemetry use the `events` table or your APM. Authed because it's intended for operators, not end users.","tags":["meta"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkersHealthResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"}]}},"/v2/pools":{"get":{"summary":"List pools created by this API key","description":"Cursor-paginated. Filter by `type` to narrow to DBC or DAMM v2.","tags":["pools"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Page size, 1–100. Default 20."},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor returned by the previous response's `meta.next_cursor`."},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","enum":["dbc","damm_v2"],"description":"Pool family. `dbc` = Meteora Dynamic Bonding Curve (launch). `damm_v2` = Meteora CP-AMM (post-migration)."},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","enum":["pending","live","migration_triggered","migrated","failed"]},"required":false,"name":"status","in":"query"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolListResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"post":{"summary":"Create a pool","description":"Returns unsigned transactions for the client to sign + submit. Defaults to DBC; pass `type: \"damm_v2\"` for direct DAMM v2 creation (when supported).","tags":["pools"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolCreateRequest"}}}},"responses":{"200":{"description":"Pool created (unsigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolCreatedResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pools/{address}":{"get":{"summary":"Get a pool (polymorphic)","description":"Returns the unified pool resource. The `type` discriminator tells you whether to interpret `state` as DBC or DAMM v2.","tags":["pools"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"address","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/pools/{address}/verifications":{"post":{"summary":"Verify a pool went live on-chain","description":"Marks the pool as `live` once the on-chain init tx has finalized. Optionally accepts a signed bundle to submit first.","tags":["pools"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"address","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolVerificationRequest"}}}},"responses":{"200":{"description":"Verified","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolVerificationResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/pools/{address}/curve-progress":{"get":{"summary":"Fraction of bonding-curve migration threshold reached","tags":["pools"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"address","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurveProgressResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/pools/{address}/fee-metrics":{"get":{"summary":"Read partner fee + surplus metrics for a pool","tags":["fee-claims"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"address","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolFeeMetricsResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/pools/{address}/fee-claims":{"post":{"summary":"Claim partner fees (and optionally split atomically)","description":"Replaces v1's `/fees/dbc/claim`, `/fees/dammv2/claim`, `/fees/surplus/withdraw`, and `/fees/split` with a single resource. Use `kind` to select the claim variant; provide `splits` to claim+split in one tx (DBC only).","tags":["fee-claims"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"address","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeeClaimCreateRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeeClaimResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"get":{"summary":"List historical fee claims for a pool","description":"Reads from the `events` table. Cursor-paginated.","tags":["fee-claims"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"address","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Page size, 1–100. Default 20."},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor returned by the previous response's `meta.next_cursor`."},"required":false,"name":"cursor","in":"query"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeeClaimHistoryResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/airdrops":{"get":{"summary":"List airdrops","description":"Cursor-paginated. Backed by the `merkle_trees` table — every persisted tree surfaces as an airdrop resource. Status defaults to `tree_built`; transitions past it require a future tx-watcher.","tags":["airdrops"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Page size, 1–100. Default 20."},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor returned by the previous response's `meta.next_cursor`."},"required":false,"name":"cursor","in":"query"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AirdropListResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"post":{"summary":"Create an on-chain airdrop config","description":"Builds the `initializeAirdrop` transaction for the Pirates Anchor program. With `mode: unsigned` the caller signs and submits; with `mode: signed` the server signs via Privy and broadcasts (requires `airdrop:admin` scope). Replaces v1 `/airdrops/init`.","tags":["airdrops"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AirdropCreateRequest"}}}},"responses":{"200":{"description":"Airdrop created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AirdropCreatedResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/airdrops/{id}":{"get":{"summary":"Get an airdrop","description":"`{id}` is the opaque composite id (base64url of `mint:airdrop_count`) returned from `POST /v2/merkle-trees` or `POST /v2/airdrops`.","tags":["airdrops"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AirdropResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/airdrops/{id}/claims":{"post":{"summary":"Build a claim transaction","description":"Builds an unsigned `claimAirdrop` transaction. The claimer wallet must sign — `mode: signed` is rejected with 400. If `proof` is omitted the server resolves it from the stored merkle tree. When `swap_to_sol: true` an auxiliary Jupiter swap-to-SOL tx is included in the response.\n\nReplaces v1 `/airdrops/claim`.","tags":["airdrops"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AirdropClaimRequest"}}}},"responses":{"200":{"description":"Claim transaction built","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AirdropClaimResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/airdrops/{id}/vault-withdrawals":{"post":{"summary":"Drain unclaimed tokens from the airdrop vault","description":"Admin-only. Always server-signed via Privy and submitted. Emits `airdrop.vault_drained`. Replaces v1 `/airdrops/withdraw-unclaimed`.","tags":["airdrops"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AirdropVaultWithdrawalRequest"}}}},"responses":{"200":{"description":"Withdrawn","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AirdropVaultWithdrawalResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/merkle-trees":{"post":{"summary":"Build (and optionally persist) a merkle tree","description":"Computes a keccak256 merkle tree over `entries`, compatible with the Pirates Anchor program's on-chain `verify_merkle_proof`. When `persist: true` the tree is stored server-side under the composite key `mint:airdrop_count`; the returned `id` is the base64url encoding of that key and can be passed to `GET /v2/merkle-trees/{id}/proofs/{wallet}` or to the `/v2/airdrops` endpoints.\n\nReplaces v1 `/airdrops/tree/build`.","tags":["merkle-trees"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerkleTreeCreateRequest"}}}},"responses":{"200":{"description":"Tree built","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerkleTreeResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/merkle-trees/{id}/proofs/{wallet}":{"get":{"summary":"Fetch a merkle proof for a wallet","description":"Returns the proof + amount + root needed to claim against the on-chain airdrop. `id` is the opaque composite identifier returned from `POST /v2/merkle-trees` (base64url of `mint:airdrop_count`).","tags":["merkle-trees"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"wallet","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"Proof found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerkleProofResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/stakes":{"post":{"summary":"Acquire a stake on an NFT asset","description":"Builds an unsigned tx that attaches the stake plugin to the supplied mpl-core asset. The user wallet must sign; `mode=signed` is rejected.","tags":["stakes"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StakeCreateRequest"}}}},"responses":{"200":{"description":"Stake tx built (unsigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StakeTxResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/stakes/{asset}":{"delete":{"summary":"Release a stake on an NFT asset","description":"Builds an unsigned tx that removes the stake plugin from the supplied mpl-core asset. The path parameter is the asset address because stake state lives on the asset itself. `mode=signed` is rejected.","tags":["stakes"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"asset","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StakeReleaseRequest"}}}},"responses":{"200":{"description":"Release tx built (unsigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StakeTxResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/stakes/{wallet}":{"get":{"summary":"Look up stake state for a wallet (placeholder)","description":"Stake state is encoded on the mpl-core asset plugin, not in a server-side DB. Today this endpoint returns the wallet plus a note steering callers to `/v2/accounts/{asset}` for decoding. A richer parser is a follow-up.","tags":["stakes"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"wallet","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StakeLookupResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/nfts":{"post":{"summary":"Mint an NFT under a collection","description":"Builds an unsigned tx that mints a fresh mpl-core asset into the supplied collection. The payer wallet must sign; `mode=signed` is rejected.","tags":["nfts"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NftMintRequest"}}}},"responses":{"200":{"description":"Mint tx built (unsigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NftTxResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/nfts/{asset}":{"delete":{"summary":"Burn an NFT asset","description":"Builds an unsigned tx that burns the supplied mpl-core asset. The owner wallet must sign; `mode=signed` is rejected.","tags":["nfts"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"asset","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NftBurnRequest"}}}},"responses":{"200":{"description":"Burn tx built (unsigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NftTxResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/gold-locks":{"post":{"summary":"Lock GOLD and mint veGOLD","description":"Builds an unsigned tx that locks the supplied amount of GOLD for `lock_duration_days` and mints veGOLD to the user. The user wallet must sign; `mode=signed` is rejected.","tags":["gold-locks"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoldLockCreateRequest"}}}},"responses":{"200":{"description":"Lock tx built (unsigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoldLockTxResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/gold-locks/{user}":{"delete":{"summary":"Unlock GOLD","description":"Builds an unsigned tx that returns the user's locked GOLD (burning veGOLD) once the lock has matured. The path parameter is the user wallet. `mode=signed` is rejected.","tags":["gold-locks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"user","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoldLockReleaseRequest"}}}},"responses":{"200":{"description":"Unlock tx built (unsigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoldLockTxResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/tokens":{"post":{"summary":"Create an SPL token with Metaplex metadata","description":"Builds a single VersionedTransaction that creates the mint, the associated token account, mints the initial supply, and writes the Metaplex metadata account. Optionally revokes mint and/or freeze authority in the same tx. `mode=signed` is rejected — the payer must sign locally.","tags":["tokens"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenCreateRequest"}}}},"responses":{"200":{"description":"Token creation tx built (unsigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenCreatedResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/tokens/{mint}/authorities/{type}":{"delete":{"summary":"Revoke a token authority","description":"Builds an unsigned tx setting the chosen authority (`mint` or `freeze`) to null. Must be signed by the current holder of that authority. `mode=signed` is rejected.","tags":["tokens"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"mint","in":"path"},{"schema":{"type":"string","enum":["mint","freeze"],"description":"Which SPL token authority to operate on."},"required":true,"name":"type","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRevokeAuthorityRequest"}}}},"responses":{"200":{"description":"Revoke tx built (unsigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRevokeAuthorityResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/tokens/{mint}":{"get":{"summary":"Get token metadata","description":"Fetches token metadata via Helius `getAsset`. The vendor payload is returned under `raw`; a normalized `status` lifecycle field is included.","tags":["tokens"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"mint","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/transactions":{"post":{"summary":"Submit a signed transaction (or Jito bundle)","description":"Submits one signed `VersionedTransaction` to the network, OR — when `bundle: true` — submits 1–5 signed transactions atomically as a Jito bundle. Replaces `/v1/tx/submit` and `/v1/tx/submit-jito`. Emits `transaction.submitted`.","tags":["transactions"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionSubmitRequest"}}}},"responses":{"200":{"description":"Submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionSubmitResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/transactions/{signature}":{"get":{"summary":"Get a transaction's on-chain status","description":"Returns the full transaction resource: `signature`, `lifecycle` (unknown → submitted → processing → confirmed → finalized, or failed), `confirmation_status`, `err`, `slot`, and `confirmations`. Replaces `/v1/tx/{sig}/status`. Stop-gap: emits `transaction.${lifecycle}` on every GET that observes a non-`unknown` state, since we have no persisted prior state to diff against.","tags":["transactions"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"signature","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/transaction-simulations":{"post":{"summary":"Simulate a transaction without submitting","description":"Runs `simulateTransaction` against the cluster and returns the raw RPC result wrapped under `data.raw`. Replaces `/v1/tx/simulate`.","tags":["transactions"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionSimulationRequest"}}}},"responses":{"200":{"description":"Simulated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionSimulationResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/swap-quotes":{"post":{"summary":"Get a Jupiter swap quote","description":"Passthrough to Jupiter's `/quote` endpoint. Converted from v1's `GET /v1/swap/quote` so we can ride the standard `{ data, meta }` envelope and accept richer parameters. The returned `data.quote` shape mirrors Jupiter's response verbatim — pass it back into `POST /v2/swaps` as-is.","tags":["swaps"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SwapQuoteRequest"}}}},"responses":{"200":{"description":"Quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SwapQuoteResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/swaps":{"post":{"summary":"Build an unsigned Jupiter swap transaction","description":"Takes a `quote_response` (from `POST /v2/swap-quotes`) plus the user's wallet and returns a base64 `VersionedTransaction` for the client to sign and submit (via `POST /v2/transactions`). Replaces `POST /v1/swap/tx`.","tags":["swaps"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SwapBuildRequest"}}}},"responses":{"200":{"description":"Swap transaction built","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SwapResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/platform":{"post":{"summary":"Derive the platform PDA","description":"Derives the `platform` PDA. Seeds: [`platform`, platform_id (utf8 bytes)].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/treasury":{"post":{"summary":"Derive the treasury PDA","description":"Derives the `treasury` PDA. Seeds: [`treasury`, platform_state].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TreasuryPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/airdrop-config":{"post":{"summary":"Derive the airdrop_config PDA","description":"Derives the `airdrop_config` PDA. Seeds: [`airdrop_config`, mint, airdrop_count (u16 LE)].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AirdropConfigPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/claim-airdrop":{"post":{"summary":"Derive the claim_airdrop PDA","description":"Derives the `claim_airdrop` PDA. Seeds: [`claim_airdrop`, mint, user, airdrop_config].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimAirdropPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/user-nft-config":{"post":{"summary":"Derive the user_nft_config PDA","description":"Derives the `user_nft_config` PDA. Seeds: [`user_nft_config`, user].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserNftConfigPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/gold-lock-config":{"post":{"summary":"Derive the gold_lock_config PDA","description":"Derives the `gold_lock_config` PDA. Seeds: [`gold_lock_config`, platform_state].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoldLockConfigPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/user-lock-config":{"post":{"summary":"Derive the user_lock_config PDA","description":"Derives the `user_lock_config` PDA. Seeds: [`user_lock_config`, user, platform_state].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLockConfigPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/gold-vault":{"post":{"summary":"Derive the gold_vault PDA","description":"Derives the `gold_vault` PDA. Seeds: [`gold_vault`, platform_state].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoldVaultPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/ve-gold-mint":{"post":{"summary":"Derive the ve_gold_mint PDA","description":"Derives the `ve_gold_mint` PDA. Seeds: [`ve_gold_mint`, platform_state].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VeGoldMintPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/pdas/user-ve-gold":{"post":{"summary":"Derive the user_ve_gold PDA","description":"Derives the `user_ve_gold` PDA. Seeds: [`user_ve_gold`, user, platform_state].","tags":["pdas"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserVeGoldPdaRequest"}}}},"responses":{"200":{"description":"Derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdaResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/accounts/{address}":{"get":{"summary":"Fetch a Solana account","description":"Returns raw account info (lamports as u64-safe string, owner, executable, rent epoch, base64 data). Returns 404 when the address has never been initialized.","tags":["accounts"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"address","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/accounts/batch-fetch":{"post":{"summary":"Fetch up to 100 accounts in one call","description":"Single batched RPC call; results are returned in the same order as the request `addresses` array. Missing accounts are represented as `{ exists: false, lamports: null, ... }` instead of being omitted.","tags":["accounts"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountBatchFetchRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountBatchFetchResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/webhook-event-types":{"get":{"summary":"List all canonical event types","description":"Returns the full event catalog with detection mode (synchronous, tx_confirmed, polling_required). Use this to decide which events to subscribe to.","tags":["webhooks"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventCatalogResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"}]}},"/v2/webhook-subscriptions":{"get":{"summary":"List webhook subscriptions for this API key","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Page size, 1–100. Default 20."},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor returned by the previous response's `meta.next_cursor`."},"required":false,"name":"cursor","in":"query"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSubscriptionListResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"post":{"summary":"Create a webhook subscription","description":"The full signing secret is **only returned once** in this response. Store it securely; subsequent reads only return a 4-character preview. Verify webhook deliveries by recomputing `HMAC-SHA256(secret, timestamp + \".\" + body)` and comparing with the `X-Pirate-Signature` header.","tags":["webhooks"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSubscriptionCreateRequest"}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSubscriptionWithSecretResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/v2/webhook-subscriptions/{id}":{"get":{"summary":"Get a webhook subscription","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSubscriptionResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"patch":{"summary":"Update a webhook subscription","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSubscriptionUpdateRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSubscriptionResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"delete":{"summary":"Delete a webhook subscription","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSubscriptionResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v2/webhook-subscriptions/{id}/test":{"post":{"summary":"Fire a synthetic `webhook.test_event` to this subscription","description":"POSTs a signed `webhook.test_event` directly to the subscription URL — bypasses the worker queue and the `enabled_events` filter. Use this to verify your signature-verification implementation end-to-end. Returns the upstream HTTP status, response body snippet, and duration so you can debug without waiting on a real event.","tags":["webhooks"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Test delivery result (success OR upstream failure — both 200 here; check `delivered`)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"subscription_id":{"type":"string"},"event_id":{"type":"string"},"delivered":{"type":"boolean"},"status_code":{"type":"number","nullable":true},"response_snippet":{"type":"string","nullable":true},"error":{"type":"string","nullable":true},"duration_ms":{"type":"number"}},"required":["subscription_id","event_id","delivered","status_code","response_snippet","error","duration_ms"]},"meta":{"type":"object","properties":{"request_id":{"type":"string"}},"required":["request_id"]}},"required":["data","meta"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"Missing or malformed API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"API key invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}}}}