diff --git a/.gitattributes b/.gitattributes index d207b180..e244b07f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,3 @@ *.go text eol=lf +specs/** -text +conformance/** text eol=lf diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 90c06fc2..8f36df0d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,15 +1,19 @@ # Release and security-sensitive repository controls. -/.github/CODEOWNERS @fuller @ximt -/.github/workflows/** @fuller @ximt +/.github/CODEOWNERS @gemini/principal-engineers +/.github/workflows/** @gemini/principal-engineers /.github/workflows/publish-typescript-sdk.yml @gemini/principal-engineers -/SECURITY.md @fuller @ximt +/SECURITY.md @gemini/principal-engineers # Published TypeScript SDK source. -/packages/sdk-typescript/** @fuller @ximt +/packages/sdk-typescript/** @gemini/principal-engineers # Published TypeScript SDK release metadata. /packages/sdk-typescript/package.json @gemini/principal-engineers /packages/sdk-typescript/package-lock.json @gemini/principal-engineers # Published Go SDK source, module metadata, and release workflow. -/packages/sdk-go/** @fuller @ximt +/packages/sdk-go/** @gemini/principal-engineers + +# Cross-SDK API contract and conformance fixtures. +/specs/** @gemini/principal-engineers +/conformance/** @gemini/principal-engineers diff --git a/.github/workflows/validate-go-sdk.yml b/.github/workflows/validate-go-sdk.yml index 60493791..6546a4f3 100644 --- a/.github/workflows/validate-go-sdk.yml +++ b/.github/workflows/validate-go-sdk.yml @@ -4,6 +4,8 @@ on: pull_request: paths: - "packages/sdk-go/**" + - "specs/**" + - "conformance/**" - ".github/workflows/validate-go-sdk.yml" - ".github/workflows/release-go-sdk.yml" diff --git a/.github/workflows/validate-typescript-sdk.yml b/.github/workflows/validate-typescript-sdk.yml index bff8ebd4..53ae7763 100644 --- a/.github/workflows/validate-typescript-sdk.yml +++ b/.github/workflows/validate-typescript-sdk.yml @@ -4,6 +4,8 @@ on: pull_request: paths: - "packages/sdk-typescript/**" + - "specs/**" + - "conformance/**" - ".github/workflows/validate-typescript-sdk.yml" permissions: diff --git a/conformance/README.md b/conformance/README.md new file mode 100644 index 00000000..ed04b621 --- /dev/null +++ b/conformance/README.md @@ -0,0 +1,189 @@ +# API contract conformance fixtures + +This directory is the language-neutral wire contract for the Gemini SDKs. The +fixtures are deterministic, contain no credentials that grant access, and do +not call the network. A runner loads `manifest.json`, executes every case in +its listed suite, and asserts the observable request, response, decoded value, +or WebSocket frame described by that case. + +## Manifest and layout + +`manifest.json` is the single case enumeration. Each suite has an `id`, a +`kind`, and a list of case file names. A case is stored at +`conformance//.json`; for example, +`http/errors/not-found-404-empty-body.json`. The top-level `exceptions` array +is the authoritative list of reviewed cross-SDK tolerances. It must contain +the same IDs as `specs/overlays/gemini-wire-exceptions.yaml`. + +Runners enforce the contract in both directions: every manifest entry must +have exactly one JSON file, and every fixture JSON file (other than the +manifest itself) must be listed. They also reject a manifest that silently +shrinks coverage. Case-level `exceptions` references must be declared in the +wire-exceptions overlay, and overlay IDs must be represented in the manifest +(the overlay may intentionally declare an ID with no cases). + +All files are UTF-8 JSON with LF line endings. Values that are significant on +the wire are represented as strings or raw JSON numbers in the fixture; a +runner must preserve number text rather than passing unsafe integers through a +platform-sized floating-point value. + +## Case schemas + +The six `kind` values are described below. Fields not marked optional are +required. `id` is always the full path `/` and `kind` must +match its manifest suite. + +### `hmacRequest` + +```json +{ + "id": "http/hmac-requests/example", + "kind": "hmacRequest", + "credentials": { "apiKey": "...", "apiSecret": "..." }, + "nonce": { "mode": "monotonic", "value": "1700000000000" }, + "request": { "method": "POST", "path": "/v1/order/new", "body": {} }, + "expect": { + "headers": ["X-GEMINI-APIKEY", "X-GEMINI-PAYLOAD", "X-GEMINI-SIGNATURE"], + "apiKeyHeader": "...", + "payload": { "request": "/v1/order/new", "nonce": "...", "fields": {} }, + "signature": { "algorithm": "HMAC-SHA384", "over": "payloadBase64", "encoding": "hex-lower" } + }, + "exceptions": ["rest-nonce-json-type"] +} +``` + +`nonce.mode` is `monotonic` (the exact decimal `value` is supplied) or +`websocket` (no exact value is supplied). For a monotonic request, the runner +sends the request through the SDK's HTTP signing seam. Every expected header +must be present and non-empty; the API-key header must equal `apiKeyHeader`. +Base64-decode `X-GEMINI-PAYLOAD`, parse it losslessly, and assert `request`, +nonce decimal text (allowing optional JSON string quotes), and every declared +field's raw JSON value. The payload may contain only `request`, `nonce`, and +the declared fields. Recompute HMAC-SHA384 over the base64 payload text and +compare the lowercase hexadecimal signature. For `websocket` nonce cases, +assert that `X-GEMINI-PAYLOAD` decodes to the `X-GEMINI-NONCE` value, that the +nonce is ten decimal epoch-second digits, and that the signature verifies. + +### `unsignedRequest` + +```json +{ + "id": "http/unsigned-requests/example", + "kind": "unsignedRequest", + "operation": "marketData.getTicker", + "input": { "symbol": "BTCUSD" }, + "expect": { + "method": "GET", + "path": "/v1/pubticker/BTCUSD", + "query": {}, + "authHeaders": [] + } +} +``` + +`operation` identifies the SDK service wrapper. The runner invokes it with +`input` through a capturing HTTP transport and asserts method, path, query +values, and absence of authentication headers. Array query values are +repeated plain keys (not comma-joined); query object ordering is not +significant. + +### `errorMapping` + +```json +{ + "id": "http/errors/example", + "kind": "errorMapping", + "response": { + "status": 403, + "headers": { "content-type": "application/json" }, + "body": "{\"result\":\"error\",\"reason\":\"MissingRole\"}" + }, + "expect": { "kind": "missing_role", "reason": "MissingRole" } +} +``` + +`response.body` is verbatim response text. Runners feed the status, headers, +and body through their SDK transport and map the canonical expected kinds: +`invalid_nonce`, `missing_nonce`, `invalid_signature`, `missing_role`, +`terms_required`, `insufficient_funds`, `rate_limited`, `order_not_found`, +`market_closed`, `not_found`, `service_error`, and `invalid_request`. +Observed status must match. If `reason` is present, it must be preserved on +the resulting error. The rate-limit case also has +`retryAfterSeconds` and requires the SDK's retry-after metadata to equal that +number (three seconds in the checked-in fixture). + +### `jsonDecoding` + +```json +{ + "id": "json/example", + "kind": "jsonDecoding", + "raw": "{\"v\":9007199254740993}", + "field": "v", + "expect": { "valueKind": "integer", "text": "9007199254740993" } +} +``` + +`raw` is the exact JSON input and `field` identifies the decoded value. +`valueKind` is `integer` or `decimal`. The runner decodes with its lossless +JSON path, or with the language's exact integer/decimal type, and renders the +value as the expected decimal text. Unsafe integers must never be rounded; +decimal strings and decimal JSON numbers must retain their exact value. + +### `wsSubscription` + +```json +{ + "id": "websocket/subscriptions/example", + "kind": "wsSubscription", + "stream": "trades", + "symbol": "BTCUSD", + "options": {}, + "expect": { "method": "SUBSCRIBE", "params": ["btcusd@trade"] }, + "exceptions": ["ws-subscription-id-scope"] +} +``` + +`stream` is one of `trades`, `bookTicker`, `depthUpdates`, `partialDepth`, +`contractStatus`, `orders`, `balances`, or `positions`. `symbol` is required +for symbol streams and omitted for global/private streams. `options` may +contain `intervalMs` (100 or 1000 as applicable), `levels` (5, 10, or 20), or +private `scope` (`account` or `session`). The runner maps the stream to the +SDK's typed call, captures the single wire frame, and asserts `method`, exact +`params`, and a positive integer `id`. It must acknowledge the request locally; +no network or wall-clock value is needed for this assertion. + +### `wsEvent` + +```json +{ + "id": "websocket/events/example", + "kind": "wsEvent", + "stream": "trades", + "symbol": "BTCUSD", + "frame": "{\"e\":\"trade\",\"s\":\"btcusd\"}", + "expect": { + "fields": { + "s": { "text": "BTCUSD", "compare": "caseInsensitive" } + } + }, + "exceptions": ["ws-inbound-symbol-case"] +} +``` + +`frame` is verbatim inbound WebSocket JSON. `stream` selects the typed SDK +subscription and `expect.fields` names decoded wire fields. Each field has +expected rendered `text` and `compare` of `exact` or `caseInsensitive`. +Runners assert that events are delivered to the selected subscription; the +case-insensitive comparison is used only for the reviewed symbol-case +exception. Wide update IDs are compared by decimal text. + +## Implementing another runner + +A new SDK runner should iterate suites from `manifest.json` rather than +hard-code case names, load each case from its suite directory, and implement +all six schemas above. It should use an in-memory HTTP/WebSocket double, +perform independent signature verification, preserve raw numeric text, and +fail on missing, extra, or unlisted fixtures. It must also compare the +manifest exception IDs and every case exception reference with the reviewed +wire-exceptions overlay before executing behavioral cases. diff --git a/conformance/http/errors/insufficient-funds-406.json b/conformance/http/errors/insufficient-funds-406.json new file mode 100644 index 00000000..f1410227 --- /dev/null +++ b/conformance/http/errors/insufficient-funds-406.json @@ -0,0 +1,13 @@ +{ + "id": "http/errors/insufficient-funds-406", + "kind": "errorMapping", + "response": { + "status": 406, + "headers": { "content-type": "application/json" }, + "body": "{\"result\":\"error\",\"reason\":\"InsufficientFunds\",\"message\":\"Insufficient funds\"}" + }, + "expect": { + "kind": "insufficient_funds", + "reason": "InsufficientFunds" + } +} diff --git a/conformance/http/errors/invalid-nonce-400.json b/conformance/http/errors/invalid-nonce-400.json new file mode 100644 index 00000000..f7862e6b --- /dev/null +++ b/conformance/http/errors/invalid-nonce-400.json @@ -0,0 +1,13 @@ +{ + "id": "http/errors/invalid-nonce-400", + "kind": "errorMapping", + "response": { + "status": 400, + "headers": { "content-type": "application/json" }, + "body": "{\"result\":\"error\",\"reason\":\"InvalidNonce\",\"message\":\"Nonce must be greater than the previous nonce\"}" + }, + "expect": { + "kind": "invalid_nonce", + "reason": "InvalidNonce" + } +} diff --git a/conformance/http/errors/market-closed-400.json b/conformance/http/errors/market-closed-400.json new file mode 100644 index 00000000..3cea6e70 --- /dev/null +++ b/conformance/http/errors/market-closed-400.json @@ -0,0 +1,13 @@ +{ + "id": "http/errors/market-closed-400", + "kind": "errorMapping", + "response": { + "status": 400, + "headers": { "content-type": "application/json" }, + "body": "{\"result\":\"error\",\"reason\":\"MarketClosed\",\"message\":\"Market is closed\"}" + }, + "expect": { + "kind": "market_closed", + "reason": "MarketClosed" + } +} diff --git a/conformance/http/errors/missing-role-403-error-envelope.json b/conformance/http/errors/missing-role-403-error-envelope.json new file mode 100644 index 00000000..c953f4fe --- /dev/null +++ b/conformance/http/errors/missing-role-403-error-envelope.json @@ -0,0 +1,13 @@ +{ + "id": "http/errors/missing-role-403-error-envelope", + "kind": "errorMapping", + "response": { + "status": 403, + "headers": { "content-type": "application/json" }, + "body": "{\"error\":\"MissingRole\",\"message\":\"OrderStatus required\"}" + }, + "expect": { + "kind": "missing_role", + "reason": "MissingRole" + } +} diff --git a/conformance/http/errors/missing-role-403-result-envelope.json b/conformance/http/errors/missing-role-403-result-envelope.json new file mode 100644 index 00000000..ba48ce22 --- /dev/null +++ b/conformance/http/errors/missing-role-403-result-envelope.json @@ -0,0 +1,13 @@ +{ + "id": "http/errors/missing-role-403-result-envelope", + "kind": "errorMapping", + "response": { + "status": 403, + "headers": { "content-type": "application/json" }, + "body": "{\"result\":\"error\",\"reason\":\"MissingRole\",\"message\":\"OrderStatus required\"}" + }, + "expect": { + "kind": "missing_role", + "reason": "MissingRole" + } +} diff --git a/conformance/http/errors/not-found-404-empty-body.json b/conformance/http/errors/not-found-404-empty-body.json new file mode 100644 index 00000000..db305347 --- /dev/null +++ b/conformance/http/errors/not-found-404-empty-body.json @@ -0,0 +1,12 @@ +{ + "id": "http/errors/not-found-404-empty-body", + "kind": "errorMapping", + "response": { + "status": 404, + "headers": {}, + "body": "" + }, + "expect": { + "kind": "not_found" + } +} diff --git a/conformance/http/errors/order-not-found-404.json b/conformance/http/errors/order-not-found-404.json new file mode 100644 index 00000000..40c0b121 --- /dev/null +++ b/conformance/http/errors/order-not-found-404.json @@ -0,0 +1,13 @@ +{ + "id": "http/errors/order-not-found-404", + "kind": "errorMapping", + "response": { + "status": 404, + "headers": { "content-type": "application/json" }, + "body": "{\"result\":\"error\",\"reason\":\"OrderNotFound\",\"message\":\"Order not found\"}" + }, + "expect": { + "kind": "order_not_found", + "reason": "OrderNotFound" + } +} diff --git a/conformance/http/errors/rate-limited-429-retry-after.json b/conformance/http/errors/rate-limited-429-retry-after.json new file mode 100644 index 00000000..be6c950b --- /dev/null +++ b/conformance/http/errors/rate-limited-429-retry-after.json @@ -0,0 +1,17 @@ +{ + "id": "http/errors/rate-limited-429-retry-after", + "kind": "errorMapping", + "response": { + "status": 429, + "headers": { + "content-type": "application/json", + "retry-after": "3" + }, + "body": "{\"result\":\"error\",\"reason\":\"RateLimit\",\"message\":\"Rate limit exceeded\"}" + }, + "expect": { + "kind": "rate_limited", + "reason": "RateLimit", + "retryAfterSeconds": 3 + } +} diff --git a/conformance/http/errors/server-error-500-unstructured.json b/conformance/http/errors/server-error-500-unstructured.json new file mode 100644 index 00000000..641785f5 --- /dev/null +++ b/conformance/http/errors/server-error-500-unstructured.json @@ -0,0 +1,12 @@ +{ + "id": "http/errors/server-error-500-unstructured", + "kind": "errorMapping", + "response": { + "status": 500, + "headers": { "content-type": "text/plain" }, + "body": "upstream unavailable" + }, + "expect": { + "kind": "service_error" + } +} diff --git a/conformance/http/errors/terms-required-400-accept-terms-required.json b/conformance/http/errors/terms-required-400-accept-terms-required.json new file mode 100644 index 00000000..f150a728 --- /dev/null +++ b/conformance/http/errors/terms-required-400-accept-terms-required.json @@ -0,0 +1,13 @@ +{ + "id": "http/errors/terms-required-400-accept-terms-required", + "kind": "errorMapping", + "response": { + "status": 400, + "headers": { "content-type": "application/json" }, + "body": "{\"result\":\"error\",\"reason\":\"AcceptTermsRequired\",\"message\":\"Terms must be accepted before placing orders\"}" + }, + "expect": { + "kind": "terms_required", + "reason": "AcceptTermsRequired" + } +} diff --git a/conformance/http/errors/terms-required-400-must-accept.json b/conformance/http/errors/terms-required-400-must-accept.json new file mode 100644 index 00000000..1e2a4b41 --- /dev/null +++ b/conformance/http/errors/terms-required-400-must-accept.json @@ -0,0 +1,13 @@ +{ + "id": "http/errors/terms-required-400-must-accept", + "kind": "errorMapping", + "response": { + "status": 400, + "headers": { "content-type": "application/json" }, + "body": "{\"result\":\"error\",\"reason\":\"MustAccepTerms\",\"message\":\"Terms must be accepted before placing orders\"}" + }, + "expect": { + "kind": "terms_required", + "reason": "MustAccepTerms" + } +} diff --git a/conformance/http/hmac-requests/private-post-empty-body.json b/conformance/http/hmac-requests/private-post-empty-body.json new file mode 100644 index 00000000..764e3cb5 --- /dev/null +++ b/conformance/http/hmac-requests/private-post-empty-body.json @@ -0,0 +1,38 @@ +{ + "id": "http/hmac-requests/private-post-empty-body", + "kind": "hmacRequest", + "credentials": { + "apiKey": "conformance-api-key", + "apiSecret": "conformance-api-secret" + }, + "nonce": { + "mode": "monotonic", + "value": "1700000000001" + }, + "request": { + "method": "POST", + "path": "/v1/order/status", + "body": {} + }, + "expect": { + "headers": [ + "X-GEMINI-APIKEY", + "X-GEMINI-PAYLOAD", + "X-GEMINI-SIGNATURE" + ], + "apiKeyHeader": "conformance-api-key", + "payload": { + "request": "/v1/order/status", + "nonce": "1700000000001", + "fields": {} + }, + "signature": { + "algorithm": "HMAC-SHA384", + "over": "payloadBase64", + "encoding": "hex-lower" + } + }, + "exceptions": [ + "rest-nonce-json-type" + ] +} diff --git a/conformance/http/hmac-requests/private-post-wide-integer.json b/conformance/http/hmac-requests/private-post-wide-integer.json new file mode 100644 index 00000000..f485fd22 --- /dev/null +++ b/conformance/http/hmac-requests/private-post-wide-integer.json @@ -0,0 +1,39 @@ +{ + "id": "http/hmac-requests/private-post-wide-integer", + "kind": "hmacRequest", + "credentials": { + "apiKey": "conformance-api-key", + "apiSecret": "conformance-api-secret" + }, + "nonce": { + "mode": "monotonic", + "value": "1700000000002" + }, + "request": { + "method": "POST", + "path": "/v1/order/status", + "body": { + "order_id": 9007199254740993 + } + }, + "expect": { + "headers": [ + "X-GEMINI-APIKEY", + "X-GEMINI-PAYLOAD", + "X-GEMINI-SIGNATURE" + ], + "apiKeyHeader": "conformance-api-key", + "payload": { + "request": "/v1/order/status", + "nonce": "1700000000002", + "fields": { + "order_id": 9007199254740993 + } + }, + "signature": { + "algorithm": "HMAC-SHA384", + "over": "payloadBase64", + "encoding": "hex-lower" + } + } +} diff --git a/conformance/http/hmac-requests/private-post-with-body.json b/conformance/http/hmac-requests/private-post-with-body.json new file mode 100644 index 00000000..ca9d8b4d --- /dev/null +++ b/conformance/http/hmac-requests/private-post-with-body.json @@ -0,0 +1,51 @@ +{ + "id": "http/hmac-requests/private-post-with-body", + "kind": "hmacRequest", + "credentials": { + "apiKey": "conformance-api-key", + "apiSecret": "conformance-api-secret" + }, + "nonce": { + "mode": "monotonic", + "value": "1700000000000" + }, + "request": { + "method": "POST", + "path": "/v1/order/new", + "body": { + "symbol": "BTCUSD", + "amount": "0.01", + "price": "1000.00", + "side": "buy", + "type": "exchange limit" + } + }, + "expect": { + "headers": [ + "X-GEMINI-APIKEY", + "X-GEMINI-PAYLOAD", + "X-GEMINI-SIGNATURE" + ], + "apiKeyHeader": "conformance-api-key", + "payload": { + "request": "/v1/order/new", + "nonce": "1700000000000", + "fields": { + "symbol": "BTCUSD", + "amount": "0.01", + "price": "1000.00", + "side": "buy", + "type": "exchange limit" + } + }, + "signature": { + "algorithm": "HMAC-SHA384", + "over": "payloadBase64", + "encoding": "hex-lower" + } + }, + "exceptions": [ + "rest-nonce-json-type", + "rest-payload-key-order" + ] +} diff --git a/conformance/http/hmac-requests/websocket-upgrade-nonce.json b/conformance/http/hmac-requests/websocket-upgrade-nonce.json new file mode 100644 index 00000000..e5aac88a --- /dev/null +++ b/conformance/http/hmac-requests/websocket-upgrade-nonce.json @@ -0,0 +1,26 @@ +{ + "id": "http/hmac-requests/websocket-upgrade-nonce", + "kind": "hmacRequest", + "credentials": { + "apiKey": "conformance-api-key", + "apiSecret": "conformance-api-secret" + }, + "nonce": { + "mode": "websocket" + }, + "expect": { + "headers": [ + "X-GEMINI-APIKEY", + "X-GEMINI-NONCE", + "X-GEMINI-PAYLOAD", + "X-GEMINI-SIGNATURE" + ], + "apiKeyHeader": "conformance-api-key", + "payload": {}, + "signature": { + "algorithm": "HMAC-SHA384", + "over": "payloadBase64", + "encoding": "hex-lower" + } + } +} diff --git a/conformance/http/unsigned-requests/market-data-order-book-limits.json b/conformance/http/unsigned-requests/market-data-order-book-limits.json new file mode 100644 index 00000000..2a0f5728 --- /dev/null +++ b/conformance/http/unsigned-requests/market-data-order-book-limits.json @@ -0,0 +1,19 @@ +{ + "id": "http/unsigned-requests/market-data-order-book-limits", + "kind": "unsignedRequest", + "operation": "marketData.getCurrentOrderBook", + "input": { + "symbol": "BTCUSD", + "limit_bids": 1, + "limit_asks": 1 + }, + "expect": { + "method": "GET", + "path": "/v1/book/BTCUSD", + "query": { + "limit_asks": ["1"], + "limit_bids": ["1"] + }, + "authHeaders": [] + } +} diff --git a/conformance/http/unsigned-requests/market-data-ticker.json b/conformance/http/unsigned-requests/market-data-ticker.json new file mode 100644 index 00000000..92691ea3 --- /dev/null +++ b/conformance/http/unsigned-requests/market-data-ticker.json @@ -0,0 +1,14 @@ +{ + "id": "http/unsigned-requests/market-data-ticker", + "kind": "unsignedRequest", + "operation": "marketData.getTicker", + "input": { + "symbol": "BTCUSD" + }, + "expect": { + "method": "GET", + "path": "/v1/pubticker/BTCUSD", + "query": {}, + "authHeaders": [] + } +} diff --git a/conformance/http/unsigned-requests/prediction-markets-list-events-filters.json b/conformance/http/unsigned-requests/prediction-markets-list-events-filters.json new file mode 100644 index 00000000..7a78b8ae --- /dev/null +++ b/conformance/http/unsigned-requests/prediction-markets-list-events-filters.json @@ -0,0 +1,16 @@ +{ + "id": "http/unsigned-requests/prediction-markets-list-events-filters", + "kind": "unsignedRequest", + "operation": "predictions.listEvents", + "input": { + "status": ["active", "closed"] + }, + "expect": { + "method": "GET", + "path": "/v1/prediction-markets/events", + "query": { + "status": ["active", "closed"] + }, + "authHeaders": [] + } +} diff --git a/conformance/json/decimal-number-exact.json b/conformance/json/decimal-number-exact.json new file mode 100644 index 00000000..24ed5817 --- /dev/null +++ b/conformance/json/decimal-number-exact.json @@ -0,0 +1,10 @@ +{ + "id": "json/decimal-number-exact", + "kind": "jsonDecoding", + "raw": "{\"v\":0.00000001}", + "field": "v", + "expect": { + "valueKind": "decimal", + "text": "0.00000001" + } +} diff --git a/conformance/json/decimal-string-exact.json b/conformance/json/decimal-string-exact.json new file mode 100644 index 00000000..a36568a8 --- /dev/null +++ b/conformance/json/decimal-string-exact.json @@ -0,0 +1,10 @@ +{ + "id": "json/decimal-string-exact", + "kind": "jsonDecoding", + "raw": "{\"v\":\"0.00000001\"}", + "field": "v", + "expect": { + "valueKind": "decimal", + "text": "0.00000001" + } +} diff --git a/conformance/json/wide-integer-safe.json b/conformance/json/wide-integer-safe.json new file mode 100644 index 00000000..01c01238 --- /dev/null +++ b/conformance/json/wide-integer-safe.json @@ -0,0 +1,10 @@ +{ + "id": "json/wide-integer-safe", + "kind": "jsonDecoding", + "raw": "{\"v\":9007199254740991}", + "field": "v", + "expect": { + "valueKind": "integer", + "text": "9007199254740991" + } +} diff --git a/conformance/json/wide-integer-unsafe.json b/conformance/json/wide-integer-unsafe.json new file mode 100644 index 00000000..bccf8e91 --- /dev/null +++ b/conformance/json/wide-integer-unsafe.json @@ -0,0 +1,13 @@ +{ + "id": "json/wide-integer-unsafe", + "kind": "jsonDecoding", + "raw": "{\"v\":9007199254740993}", + "field": "v", + "expect": { + "valueKind": "integer", + "text": "9007199254740993" + }, + "exceptions": [ + "int64-static-typing" + ] +} diff --git a/conformance/manifest.json b/conformance/manifest.json new file mode 100644 index 00000000..1bf61af4 --- /dev/null +++ b/conformance/manifest.json @@ -0,0 +1,86 @@ +{ + "version": 1, + "suites": [ + { + "id": "http/hmac-requests", + "kind": "hmacRequest", + "cases": [ + "private-post-with-body", + "private-post-empty-body", + "private-post-wide-integer", + "websocket-upgrade-nonce" + ] + }, + { + "id": "http/unsigned-requests", + "kind": "unsignedRequest", + "cases": [ + "market-data-ticker", + "market-data-order-book-limits", + "prediction-markets-list-events-filters" + ] + }, + { + "id": "http/errors", + "kind": "errorMapping", + "cases": [ + "invalid-nonce-400", + "missing-role-403-result-envelope", + "missing-role-403-error-envelope", + "terms-required-400-must-accept", + "terms-required-400-accept-terms-required", + "insufficient-funds-406", + "rate-limited-429-retry-after", + "order-not-found-404", + "market-closed-400", + "server-error-500-unstructured", + "not-found-404-empty-body" + ] + }, + { + "id": "json", + "kind": "jsonDecoding", + "cases": [ + "wide-integer-unsafe", + "wide-integer-safe", + "decimal-string-exact", + "decimal-number-exact" + ] + }, + { + "id": "websocket/subscriptions", + "kind": "wsSubscription", + "cases": [ + "public-trades", + "public-trades-untrimmed-symbol", + "public-book-ticker", + "public-depth-diff", + "public-depth-diff-interval", + "public-partial-depth-20", + "public-contract-status", + "private-orders-session", + "private-balances-interval" + ] + }, + { + "id": "websocket/events", + "kind": "wsEvent", + "cases": [ + "trade", + "depth-unsafe-last-update-id", + "order-update", + "balance-update" + ] + } + ], + "exceptions": [ + "rest-nonce-json-type", + "rest-payload-key-order", + "ws-subscription-id-scope", + "ws-inbound-symbol-case", + "int64-static-typing", + "http-406-insufficient-funds", + "rest-query-signing", + "candle-timeframe-spelling" + ] +} diff --git a/conformance/websocket/events/balance-update.json b/conformance/websocket/events/balance-update.json new file mode 100644 index 00000000..03c67b76 --- /dev/null +++ b/conformance/websocket/events/balance-update.json @@ -0,0 +1,13 @@ +{ + "id": "websocket/events/balance-update", + "kind": "wsEvent", + "stream": "balances", + "frame": "{\"e\":\"balanceUpdate\",\"E\":1700000000000,\"u\":1700000000001,\"B\":[{\"a\":\"USD\",\"f\":\"100.00\",\"c\":\"100.00\"}]}", + "expect": { + "fields": { + "e": { "text": "balanceUpdate", "compare": "exact" }, + "E": { "text": "1700000000000", "compare": "exact" }, + "u": { "text": "1700000000001", "compare": "exact" } + } + } +} diff --git a/conformance/websocket/events/depth-unsafe-last-update-id.json b/conformance/websocket/events/depth-unsafe-last-update-id.json new file mode 100644 index 00000000..4e8ee8db --- /dev/null +++ b/conformance/websocket/events/depth-unsafe-last-update-id.json @@ -0,0 +1,16 @@ +{ + "id": "websocket/events/depth-unsafe-last-update-id", + "kind": "wsEvent", + "stream": "depthUpdates", + "symbol": "BTCUSD", + "frame": "{\"e\":\"depthUpdate\",\"E\":1700000000000,\"s\":\"BTCUSD\",\"U\":9007199254740993,\"u\":9007199254740994,\"b\":[],\"a\":[]}", + "expect": { + "fields": { + "e": { "text": "depthUpdate", "compare": "exact" }, + "E": { "text": "1700000000000", "compare": "exact" }, + "s": { "text": "BTCUSD", "compare": "caseInsensitive" }, + "U": { "text": "9007199254740993", "compare": "exact" }, + "u": { "text": "9007199254740994", "compare": "exact" } + } + } +} diff --git a/conformance/websocket/events/order-update.json b/conformance/websocket/events/order-update.json new file mode 100644 index 00000000..0d4f7f49 --- /dev/null +++ b/conformance/websocket/events/order-update.json @@ -0,0 +1,17 @@ +{ + "id": "websocket/events/order-update", + "kind": "wsEvent", + "stream": "orders", + "symbol": "BTCUSD", + "frame": "{\"e\":\"orderUpdate\",\"E\":1700000000000,\"s\":\"BTCUSD\",\"i\":12345,\"c\":\"client-order-1\",\"S\":\"BUY\",\"o\":\"LIMIT\",\"X\":\"FILLED\",\"p\":\"1000.00\",\"q\":\"0.25\",\"z\":\"0.25\",\"Z\":\"250.00\",\"T\":1700000000001}", + "expect": { + "fields": { + "e": { "text": "orderUpdate", "compare": "exact" }, + "E": { "text": "1700000000000", "compare": "exact" }, + "s": { "text": "BTCUSD", "compare": "exact" }, + "i": { "text": "12345", "compare": "exact" }, + "X": { "text": "FILLED", "compare": "exact" }, + "T": { "text": "1700000000001", "compare": "exact" } + } + } +} diff --git a/conformance/websocket/events/trade.json b/conformance/websocket/events/trade.json new file mode 100644 index 00000000..047db7ed --- /dev/null +++ b/conformance/websocket/events/trade.json @@ -0,0 +1,21 @@ +{ + "id": "websocket/events/trade", + "kind": "wsEvent", + "stream": "trades", + "symbol": "BTCUSD", + "frame": "{\"e\":\"trade\",\"E\":1700000000000,\"s\":\"btcusd\",\"t\":123456789,\"p\":\"1000.00\",\"q\":\"0.25\",\"m\":true}", + "expect": { + "fields": { + "e": { "text": "trade", "compare": "exact" }, + "E": { "text": "1700000000000", "compare": "exact" }, + "s": { "text": "BTCUSD", "compare": "caseInsensitive" }, + "t": { "text": "123456789", "compare": "exact" }, + "p": { "text": "1000.00", "compare": "exact" }, + "q": { "text": "0.25", "compare": "exact" }, + "m": { "text": "true", "compare": "exact" } + } + }, + "exceptions": [ + "ws-inbound-symbol-case" + ] +} diff --git a/conformance/websocket/subscriptions/private-balances-interval.json b/conformance/websocket/subscriptions/private-balances-interval.json new file mode 100644 index 00000000..e8c5bfaf --- /dev/null +++ b/conformance/websocket/subscriptions/private-balances-interval.json @@ -0,0 +1,12 @@ +{ + "id": "websocket/subscriptions/private-balances-interval", + "kind": "wsSubscription", + "stream": "balances", + "options": { + "intervalMs": 1000 + }, + "expect": { + "method": "SUBSCRIBE", + "params": ["balances@account@1s"] + } +} diff --git a/conformance/websocket/subscriptions/private-orders-session.json b/conformance/websocket/subscriptions/private-orders-session.json new file mode 100644 index 00000000..a67a7488 --- /dev/null +++ b/conformance/websocket/subscriptions/private-orders-session.json @@ -0,0 +1,12 @@ +{ + "id": "websocket/subscriptions/private-orders-session", + "kind": "wsSubscription", + "stream": "orders", + "options": { + "scope": "session" + }, + "expect": { + "method": "SUBSCRIBE", + "params": ["orders@session"] + } +} diff --git a/conformance/websocket/subscriptions/public-book-ticker.json b/conformance/websocket/subscriptions/public-book-ticker.json new file mode 100644 index 00000000..708b61c9 --- /dev/null +++ b/conformance/websocket/subscriptions/public-book-ticker.json @@ -0,0 +1,10 @@ +{ + "id": "websocket/subscriptions/public-book-ticker", + "kind": "wsSubscription", + "stream": "bookTicker", + "symbol": "ETHUSD", + "expect": { + "method": "SUBSCRIBE", + "params": ["ethusd@bookTicker"] + } +} diff --git a/conformance/websocket/subscriptions/public-contract-status.json b/conformance/websocket/subscriptions/public-contract-status.json new file mode 100644 index 00000000..f15ff191 --- /dev/null +++ b/conformance/websocket/subscriptions/public-contract-status.json @@ -0,0 +1,10 @@ +{ + "id": "websocket/subscriptions/public-contract-status", + "kind": "wsSubscription", + "stream": "contractStatus", + "symbol": "BTCUSD", + "expect": { + "method": "SUBSCRIBE", + "params": ["contractStatus"] + } +} diff --git a/conformance/websocket/subscriptions/public-depth-diff-interval.json b/conformance/websocket/subscriptions/public-depth-diff-interval.json new file mode 100644 index 00000000..98cdb0f7 --- /dev/null +++ b/conformance/websocket/subscriptions/public-depth-diff-interval.json @@ -0,0 +1,13 @@ +{ + "id": "websocket/subscriptions/public-depth-diff-interval", + "kind": "wsSubscription", + "stream": "depthUpdates", + "symbol": "BTCUSD", + "options": { + "intervalMs": 100 + }, + "expect": { + "method": "SUBSCRIBE", + "params": ["btcusd@depth@100ms"] + } +} diff --git a/conformance/websocket/subscriptions/public-depth-diff.json b/conformance/websocket/subscriptions/public-depth-diff.json new file mode 100644 index 00000000..28a65893 --- /dev/null +++ b/conformance/websocket/subscriptions/public-depth-diff.json @@ -0,0 +1,10 @@ +{ + "id": "websocket/subscriptions/public-depth-diff", + "kind": "wsSubscription", + "stream": "depthUpdates", + "symbol": "BTCUSD", + "expect": { + "method": "SUBSCRIBE", + "params": ["btcusd@depth"] + } +} diff --git a/conformance/websocket/subscriptions/public-partial-depth-20.json b/conformance/websocket/subscriptions/public-partial-depth-20.json new file mode 100644 index 00000000..64cc4f64 --- /dev/null +++ b/conformance/websocket/subscriptions/public-partial-depth-20.json @@ -0,0 +1,13 @@ +{ + "id": "websocket/subscriptions/public-partial-depth-20", + "kind": "wsSubscription", + "stream": "partialDepth", + "symbol": "BTCUSD", + "options": { + "levels": 20 + }, + "expect": { + "method": "SUBSCRIBE", + "params": ["btcusd@depth20"] + } +} diff --git a/conformance/websocket/subscriptions/public-trades-untrimmed-symbol.json b/conformance/websocket/subscriptions/public-trades-untrimmed-symbol.json new file mode 100644 index 00000000..d5130dcb --- /dev/null +++ b/conformance/websocket/subscriptions/public-trades-untrimmed-symbol.json @@ -0,0 +1,10 @@ +{ + "id": "websocket/subscriptions/public-trades-untrimmed-symbol", + "kind": "wsSubscription", + "stream": "trades", + "symbol": " BTCUSD ", + "expect": { + "method": "SUBSCRIBE", + "params": ["btcusd@trade"] + } +} diff --git a/conformance/websocket/subscriptions/public-trades.json b/conformance/websocket/subscriptions/public-trades.json new file mode 100644 index 00000000..dd7ed41f --- /dev/null +++ b/conformance/websocket/subscriptions/public-trades.json @@ -0,0 +1,13 @@ +{ + "id": "websocket/subscriptions/public-trades", + "kind": "wsSubscription", + "stream": "trades", + "symbol": "BTCUSD", + "expect": { + "method": "SUBSCRIBE", + "params": ["btcusd@trade"] + }, + "exceptions": [ + "ws-subscription-id-scope" + ] +} diff --git a/skills/README.md b/skills/README.md index 3c721479..db938d23 100644 --- a/skills/README.md +++ b/skills/README.md @@ -37,6 +37,7 @@ npx skills add gemini/developer-platform -a claude-code --all -g -y | [`gemini-candles`](gemini-candles/) | Display terminal candlestick charts for Gemini trading pairs | | [`gemini-developer`](gemini-developer/) | Guide for building integrations with the Gemini API | | [`integrate-gemini`](integrate-gemini/) | Production integration skill for Gemini REST, WebSocket (wss://ws.gemini.com), and FIX 4.4 | +| [`sdk-conformance-review`](sdk-conformance-review/) | Review any SDK against checked-in API specs and shared conformance fixtures | ## Manual installation diff --git a/skills/integrate-gemini/SKILL.md b/skills/integrate-gemini/SKILL.md index 285a9598..11f9e151 100644 --- a/skills/integrate-gemini/SKILL.md +++ b/skills/integrate-gemini/SKILL.md @@ -81,7 +81,7 @@ For the structured request/response schemas, fetch the catalog first, then use i - **Prediction Markets OpenAPI Spec**: `https://developer.gemini.com/specs/openapi/prediction-markets.yaml` - **Rendered API Specifications page**: `https://developer.gemini.com/api-specifications` -This repository does not commit the OpenAPI/AsyncAPI files locally — fetch the URLs above rather than assuming a local `apis/` directory. The TypeScript SDK generators under `packages/sdk-typescript/scripts` consume the published specs and verify their reviewed content hashes; prefer the live spec URLs above when writing integration code. +For SDK generation and conformance reviews, use the checked-in `specs/SOURCES.json` and verbatim files under `specs/`; `specs/refresh.mjs` is the only contract refresh command and is the only repository path that fetches specs. For live integration work, the URLs above remain the narrative/current source. If a fetched page or spec disagrees with this skill, trust the live source and tell the user what changed — don't silently paper over the discrepancy. diff --git a/skills/integrate-gemini/reference.md b/skills/integrate-gemini/reference.md index b7b325c7..71818903 100644 --- a/skills/integrate-gemini/reference.md +++ b/skills/integrate-gemini/reference.md @@ -15,7 +15,7 @@ This reference manual provides technical specifications, HMAC-SHA384 signing cod | **FIX Market Data** | Provisioned after FIX sandbox onboarding | Provisioned after FIX production onboarding | FIX 4.4 Specification | | **FIX Drop Copy** | Provisioned after FIX sandbox onboarding | Provisioned after FIX production onboarding | FIX 4.4 Specification | -See [SKILL.md](SKILL.md#step-2-locate-canonical-specifications) for the live spec URLs — this repository does not commit them locally. +For SDK work, use the checked-in `specs/SOURCES.json` and verbatim contract files; see [SKILL.md](SKILL.md#step-2-locate-canonical-specifications) for the review workflow. The URLs above remain the live integration sources. --- diff --git a/skills/sdk-conformance-review/SKILL.md b/skills/sdk-conformance-review/SKILL.md new file mode 100644 index 00000000..7965abb0 --- /dev/null +++ b/skills/sdk-conformance-review/SKILL.md @@ -0,0 +1,205 @@ +--- +name: sdk-conformance-review +description: Review a Gemini SDK against checked-in OpenAPI and AsyncAPI contracts plus language-neutral conformance fixtures +argument-hint: "[sdk path] [language]" +allowed-tools: Read, Grep, Glob, Edit, Write, Bash +--- + +# Review SDK conformance + +Use this skill after changing an SDK, its generator, a transport/authentication path, +`specs/`, or `conformance/`. Use it before adding a new SDK so the new runner +implements the same behavioral contract instead of inventing a parallel fixture set. + +The review produces an evidence-backed result: contract revision and digests, SDK +and language reviewed, commands run, fixture coverage, intentional exceptions, and +remaining findings. Do not report conformance from source inspection alone. + +## Source precedence + +Use these sources in this order: + +1. `specs/SOURCES.json` and the verbatim files under `specs/` for structured REST, + Prediction Markets, and WebSocket definitions. +2. `conformance/README.md`, `conformance/manifest.json`, and every fixture for the + shared observable behavior. +3. `specs/overlays/numeric-types.yaml` for language-specific numeric policy and + `specs/overlays/gemini-wire-exceptions.yaml` for reviewed divergences. +4. Package tests, generated output, and implementation comments. +5. Live developer documentation for narrative context only. + +Never fetch a published specification during a review. `specs/refresh.mjs` is the +only command allowed to update contract bytes, and should run only when an explicit +contract refresh is part of the change. Dependency installation may use the package +registry when `node_modules` is absent; it is not a substitute for a spec refresh. +Never use real credentials or make live API/WebSocket calls for conformance. + +## Workflow + +### 1. Establish the review scope + +1. Locate repository guidance (`AGENTS.md` or equivalent) and read the SDK package + manifest, test commands, and generator entry points. +2. Identify the SDK path and language. Record the base revision and changed files. +3. Classify each changed file as contract, overlay, fixture, generated output, + handwritten transport/service code, test runner, or documentation. +4. Treat generated files as outputs. Review the generator and its checked-in drift + gate, not only the generated diff. + +### 2. Verify the checked-in contract and fixture index + +1. Read `specs/SOURCES.json`; confirm every listed path exists and the local bytes + hash to its recorded `sha256`. A mismatch is a contract-integrity failure. +2. Confirm spec files keep verbatim bytes. The repository must pin spec line endings + with `specs/** -text`; JSON fixtures and runner sources use LF. +3. Read `conformance/manifest.json` and `conformance/README.md`. There are six + fixture kinds: `hmacRequest`, `unsignedRequest`, `errorMapping`, `jsonDecoding`, + `wsSubscription`, and `wsEvent`. +4. Check both directions: every manifest case has exactly one JSON file, and every + fixture JSON file is listed. Case `id` and `kind` must match the suite. +5. Compare manifest exception IDs with the wire-exceptions overlay. Every case + exception reference must be declared, and every overlay case mapping must match + the case references. Empty `cases` entries are intentional reviewed exceptions. +6. Do not relax a fixture to make a failing SDK pass. Fix the SDK, update the + contract deliberately, or record a reviewed exception with concrete evidence. + +### 3. Run the SDK's conformance gates + +For the TypeScript SDK, from `packages/sdk-typescript`: + +```bash +npm ci --ignore-scripts # only when dependencies are absent +npm test # includes drift, overlay, manifest, and six runners +npm run typecheck +npm run build +npm rebuild esbuild workerd --foreground-scripts +npm run verify:package +npm run verify:runtimes +``` + +`verify:runtimes` may report Deno skipped when Deno is not installed; record that +limitation. Run the focused suites while iterating, but report the complete suite +before declaring the review complete: + +```bash +npx tsx --test src/tests/conformance/**/*.test.ts +npx tsx --test scripts/generated-drift.test.mjs scripts/numeric-overlay.test.mjs +``` + +For Go, from `packages/sdk-go`, use the repository's Make targets when the local +environment permits. Otherwise run their direct equivalents with the module's +required environment, including the conformance package, generator drift check, +`go vet`, the 32-bit compile, and release smoke test. For another language, use its +native formatter/typecheck/test/package commands and implement the same fixture +matrix; do not silently skip a kind. + +### 4. Compare generated SDK surfaces with the specs + +1. Build operation inventories from both OpenAPI documents. Compare operation IDs, + HTTP methods, paths, access mode, parameters, query serialization, response + modes/statuses/content types, and int64 paths with the generated registries. +2. Validate operation ownership. Every spec operation must be owned exactly once; + no generated registry may contain an extra or missing operation. +3. Run the generated-drift gate from vendored spec IDs. A byte mismatch is a finding + even when the runtime tests pass. +4. Compare generated model types with `numeric-types.yaml`: decimal string/number + representations, exact integer handling, unsigned extensions, and language + compatibility constraints. TypeScript must preserve unsafe JSON integers at the + boundary without widening public declarations in an unreviewed breaking change. +5. Check public entry points, declaration output, package exports, and API snapshots. + An intentional public change needs an explicit compatibility decision and a + corresponding consumer-facing check. + +### 5. Exercise the six behavioral fixture contracts + +Use `conformance/README.md` as the assertion authority: + +- **HMAC requests:** capture the HTTP/upgrade seam; require headers, decode the + payload, preserve nonce and numeric text, reject undeclared fields, and independently + recompute HMAC-SHA384 over the base64 payload. +- **Unsigned requests:** call the typed service wrapper through an in-memory HTTP + transport; assert method, path, repeated/encoded query values, no request body when + forbidden, and the exact authentication-header set. +- **Error mapping:** feed verbatim status/headers/body; assert status preservation, + canonical error class/code, reason preservation, retry-after metadata, and safe + serialized body behavior. +- **JSON decoding:** use the SDK's boundary parser or exact numeric type; prove unsafe + integers are not rounded and decimal strings/numbers retain their contract value. +- **WebSocket subscriptions:** use an in-memory socket; capture one SUBSCRIBE frame, + assert method/params and a positive integer ID, and locally acknowledge the frame. +- **WebSocket events:** inject verbatim frames into the selected typed stream; assert + routing, decoded fields, exact wide IDs, and only the documented case-insensitive + comparison exceptions. + +A runner must derive its case list from the manifest, use deterministic in-memory +HTTP/WebSocket doubles, and independently verify signatures. Hard-coded case lists, +exact session IDs, or permissive comparisons that the fixture does not authorize are +runner defects. + +### 6. Review transport and protocol code manually + +Trace at least one representative path for each changed area: + +- REST path/query rendering follows the OpenAPI style, explode, allowReserved, and + repeated-array rules. +- Private payloads contain the endpoint request path, one auth-owned nonce, only + declared caller fields, and signatures over the exact base64 text. +- Public requests do not accidentally receive private headers or bodies. +- Success response status/content type and file-vs-JSON mode follow the generated + operation contract. +- Error parsing preserves documented reason/status metadata without logging secrets. +- WebSocket channel names, symbol normalization, upgrade authentication, subscribe + acknowledgements, typed event routing, reconnect behavior, and wide numeric fields + match the AsyncAPI wire names. +- Handwritten compatibility aliases are additive, idempotent, and covered by a + consumer-observable test; never hand-edit generated output to hide drift. + +### 7. Classify findings and choose the next action + +For each discrepancy, record file/symbol, observed behavior, expected source or +fixture, severity, and a minimal reproduction. + +- **Defect:** fix the SDK or runner, add a regression test when the bug is plausible, + regenerate outputs, and rerun the affected plus complete gates. +- **Contract drift:** refresh only through `specs/refresh.mjs`, inspect operation, + schema, and API-surface diffs, then regenerate all affected SDKs. +- **Reviewed exception:** keep it explicit in the wire-exceptions overlay and point + to the fixture(s) and source lines; never hide it in a broad tolerance. +- **Coverage gap:** add a fixture for an important observable boundary or record a + concrete follow-up. Do not claim full conformance from untested operations. +- **Environment limitation:** state the exact command and missing capability. Do not + convert an unrun check into a pass. + +### 8. Onboard a new SDK + +A new SDK must add a test-only runner that: + +1. Locates `conformance/manifest.json` by walking upward from the runner, so copied + release trees work without checkout-depth assumptions. +2. Loads the manifest and overlay IDs, validates manifest/disk agreement in both + directions, and iterates all six kinds without duplicating fixture files. +3. Uses in-memory HTTP/WebSocket doubles, no credentials with access, no network, + independent signature verification, and exact numeric-text handling. +4. Exposes a package-specific command in CI and runs the same contract-integrity, + conformance, generated-surface, typecheck, and packaging checks appropriate to + that language. +5. Documents any deliberate language difference in the overlay and ties it to a + fixture or an explicit empty-case exception. + +## Review report format + +Return a compact report with: + +```text +SDK/language: ... +Contract manifest/digests: ... +Commands: ... +Fixture coverage: six kinds, N cases, all listed/unlisted checks ... +Generated surface: operation counts, drift result, API snapshot result ... +Reviewed exceptions: ... +Findings: severity | file/symbol | expected | observed | fixture/reproduction +Limitations: ... +``` + +Do not call the SDK conformant if a required command, fixture kind, generated drift +check, or contract-integrity check was skipped or failed. diff --git a/specs/SOURCES.json b/specs/SOURCES.json new file mode 100644 index 00000000..7024d37d --- /dev/null +++ b/specs/SOURCES.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "specs": [ + { + "id": "rest", + "path": "openapi/rest.yaml", + "url": "https://developer.gemini.com/specs/openapi/rest.yaml", + "sha256": "a07130327a2346e640fc115271dd18984cb9389793acf9fcce6b97ad918e44e4", + "fetchedAt": "2026-09-16T22:39:02.865Z" + }, + { + "id": "predictionMarkets", + "path": "openapi/prediction-markets.yaml", + "url": "https://developer.gemini.com/specs/openapi/prediction-markets.yaml", + "sha256": "1b7403cba3af9af5e64cdbf0a3f33a329876b5e48b2e13b8a9fffb347368b427", + "fetchedAt": "2026-09-16T22:39:03.027Z" + }, + { + "id": "websocket", + "path": "asyncapi/websocket.yaml", + "url": "https://developer.gemini.com/specs/asyncapi/websocket.yaml", + "sha256": "d83c624336f16542c3f1f4554101e7fa19bbc703012ae7bcd780c401667a5def", + "fetchedAt": "2026-09-16T22:39:03.368Z" + } + ] +} diff --git a/specs/asyncapi/websocket.yaml b/specs/asyncapi/websocket.yaml new file mode 100644 index 00000000..9eb49eef --- /dev/null +++ b/specs/asyncapi/websocket.yaml @@ -0,0 +1,1618 @@ +asyncapi: 3.0.0 +info: + title: Gemini WebSocket API + version: 0.10.7 + description: | + Machine-readable contract for the production Gemini WebSocket API at + `wss://ws.gemini.com`. + + This specification models the shared JSON request/response envelope, market + data streams, authenticated order/balance/position streams (including terminal + Prediction Markets settlement details), WebSocket order management methods, + and Prediction Markets combo RFQ streams/methods that + are documented in the Gemini API docs. + + The combo RFQ streams and methods are available in production for beta testing. + Quoting requires an eligible account with the required capabilities. + + Symbols may be spot/derivatives symbols such as `btcusd` or prediction + market instrument symbols such as `GEMI-BTC05M2606011000-UP`, depending on + the product surface. + contact: + name: Gemini API Support +defaultContentType: application/json +x-gemini-coverage: + legend: + machine-readable: Request, response, or event payload fields are modeled in this spec. + partial: The documented request or event is modeled, but at least one result payload is intentionally broad because the docs do not enumerate its fields. + docs-only: The surface is documented for humans but not modeled in this spec. + streams: + - name: "{symbol}@bookTicker" + status: machine-readable + auth: public + docs: /websocket/streams#book-ticker + - name: "{symbol}@depth5" + status: machine-readable + auth: public + docs: /websocket/streams#l2-partial-depth-streams + - name: "{symbol}@depth10" + status: machine-readable + auth: public + docs: /websocket/streams#l2-partial-depth-streams + - name: "{symbol}@depth20" + status: machine-readable + auth: public + docs: /websocket/streams#l2-partial-depth-streams + - name: "{symbol}@depth5@100ms" + status: machine-readable + auth: public + docs: /websocket/streams#l2-partial-depth-streams + - name: "{symbol}@depth10@100ms" + status: machine-readable + auth: public + docs: /websocket/streams#l2-partial-depth-streams + - name: "{symbol}@depth20@100ms" + status: machine-readable + auth: public + docs: /websocket/streams#l2-partial-depth-streams + - name: "{symbol}@depth" + status: machine-readable + auth: public + docs: /websocket/streams#l2-differential-depth-streams + - name: "{symbol}@depth@100ms" + status: machine-readable + auth: public + docs: /websocket/streams#l2-differential-depth-streams + - name: "{symbol}@trade" + status: machine-readable + auth: public + docs: /websocket/streams#trade-stream + - name: orders@account + status: machine-readable + auth: authenticated + docs: /websocket/streams#order-events + - name: orders@session + status: machine-readable + auth: authenticated + docs: /websocket/streams#order-events + - name: balances@account + status: machine-readable + auth: authenticated + docs: /websocket/streams#balance-updates + - name: balances@account@1s + status: machine-readable + auth: authenticated + docs: /websocket/streams#balance-updates + - name: positions@account + status: machine-readable + auth: authenticated + docs: /prediction-markets/websocket/streams#position-updates + - name: positions@account@1s + status: machine-readable + auth: authenticated + docs: /prediction-markets/websocket/streams#position-updates + - name: contractStatus + status: machine-readable + auth: public + docs: /websocket/streams#contract-status + - name: requestForQuote + status: machine-readable + auth: public + docs: /prediction-markets/combos-rfq/websocket-streams#requestforquote + notes: Combo RFQ WebSocket surface is available in production for beta testing; quoting requires an eligible account with the required capabilities. + - name: requestForQuote@account + status: machine-readable + auth: authenticated + docs: /prediction-markets/combos-rfq/websocket-streams#requestforquoteaccount + notes: Combo RFQ WebSocket surface is available in production for beta testing; quoting requires an eligible account with the required capabilities. + - name: requestForQuote@session + status: machine-readable + auth: authenticated + docs: /prediction-markets/combos-rfq/websocket-streams#requestforquotesession + notes: Combo RFQ WebSocket surface is available in production for beta testing; quoting requires an eligible account with the required capabilities. + methods: + - name: conninfo + status: partial + auth: public + docs: /websocket/playground#method-conninfo + notes: Request envelope is modeled; result fields are not enumerated in the docs. + - name: ping + status: partial + auth: public + docs: /websocket/playground#method-ping + notes: Request envelope is modeled; result fields are not enumerated in the docs. + - name: time + status: partial + auth: public + docs: /websocket/playground#method-time + notes: Request envelope is modeled; result fields are not enumerated in the docs. + - name: SUBSCRIBE + status: machine-readable + auth: conditional + docs: /prediction-markets/websocket/playground#method-subscribe + - name: subscribe + status: machine-readable + auth: conditional + docs: /trading/websocket/playground#method-subscribe + - name: UNSUBSCRIBE + status: machine-readable + auth: conditional + docs: /prediction-markets/websocket/playground#method-unsubscribe + - name: unsubscribe + status: machine-readable + auth: conditional + docs: /trading/websocket/playground#method-unsubscribe + - name: LIST_SUBSCRIPTIONS + status: machine-readable + auth: conditional + docs: /prediction-markets/websocket/playground#method-list_subscriptions + - name: list_subscriptions + status: machine-readable + auth: conditional + docs: /trading/websocket/playground#method-list_subscriptions + - name: depth + status: machine-readable + auth: public + docs: /websocket/playground#method-depth + - name: order.place + status: partial + auth: authenticated + docs: /websocket/playground#method-order.place + notes: Request payload is modeled; rely on `orderUpdate` events for authoritative lifecycle state. + - name: order.cancel + status: partial + auth: authenticated + docs: /websocket/playground#method-order.cancel + notes: Request payload is modeled; rely on `orderUpdate` events for authoritative lifecycle state. + - name: order.cancel_all + status: partial + auth: authenticated + docs: /websocket/playground#method-order.cancel_all + notes: Request payload is modeled; result fields are not enumerated in the docs. + - name: order.cancel_session + status: partial + auth: authenticated + docs: /websocket/playground#method-order.cancel_session + notes: Request payload is modeled; result fields are not enumerated in the docs. + - name: rfq.submit_quote + status: machine-readable + auth: authenticated + docs: /prediction-markets/combos-rfq/quote-methods#rfqsubmit_quote + notes: Combo RFQ WebSocket surface is available in production for beta testing; quoting requires an eligible account with the required capabilities. + - name: rfq.withdraw_quote + status: machine-readable + auth: authenticated + docs: /prediction-markets/combos-rfq/quote-methods#rfqwithdraw_quote + notes: Combo RFQ WebSocket surface is available in production for beta testing; quoting requires an eligible account with the required capabilities. + - name: rfq.confirm_quote + status: machine-readable + auth: authenticated + docs: /prediction-markets/combos-rfq/quote-methods#rfqconfirm_quote + notes: Combo RFQ WebSocket surface is available in production for beta testing; quoting requires an eligible account with the required capabilities. +x-gemini-authentication: + timing: websocket-upgrade + alternatives: + - scheme: geminiApiKeySignature + summary: HMAC-signed, account-scoped Gemini API key headers. + - scheme: geminiOAuthBearer + summary: OAuth 2.0 bearer token in the Authorization header. + notes: + - Authentication, when required, is supplied during the initial WebSocket upgrade; clients cannot authenticate or rotate credentials after the connection opens. + - Browser WebSocket clients cannot send custom upgrade headers for authenticated streams and methods; use a non-browser client or server-side proxy. + - Public streams and utility methods do not require authentication. Account/session streams, order methods, and combo RFQ quote methods require one of the listed authentication alternatives. +servers: + production: + host: ws.gemini.com + protocol: wss + pathname: / + description: Production WebSocket API. + sandbox: + host: ws.sandbox.gemini.com + protocol: wss + pathname: / + description: Sandbox environment. +channels: + connection: + address: / + title: WebSocket connection + description: | + JSON request/response control plane over a single WebSocket connection. + Authentication, when required, is supplied during the WebSocket upgrade. + messages: + conninfoRequest: + $ref: '#/components/messages/ConninfoRequest' + pingRequest: + $ref: '#/components/messages/PingRequest' + timeRequest: + $ref: '#/components/messages/TimeRequest' + subscribeRequest: + $ref: '#/components/messages/SubscribeRequest' + unsubscribeRequest: + $ref: '#/components/messages/UnsubscribeRequest' + listSubscriptionsRequest: + $ref: '#/components/messages/ListSubscriptionsRequest' + depthRequest: + $ref: '#/components/messages/DepthRequest' + orderPlaceRequest: + $ref: '#/components/messages/OrderPlaceRequest' + orderCancelRequest: + $ref: '#/components/messages/OrderCancelRequest' + orderCancelAllRequest: + $ref: '#/components/messages/OrderCancelAllRequest' + orderCancelSessionRequest: + $ref: '#/components/messages/OrderCancelSessionRequest' + rfqSubmitQuoteRequest: + $ref: '#/components/messages/RfqSubmitQuoteRequest' + rfqWithdrawQuoteRequest: + $ref: '#/components/messages/RfqWithdrawQuoteRequest' + rfqConfirmQuoteRequest: + $ref: '#/components/messages/RfqConfirmQuoteRequest' + genericSuccessResponse: + $ref: '#/components/messages/GenericSuccessResponse' + listSubscriptionsResponse: + $ref: '#/components/messages/ListSubscriptionsResponse' + depthResponse: + $ref: '#/components/messages/DepthResponse' + orderActionResponse: + $ref: '#/components/messages/OrderActionResponse' + rfqSubmitQuoteResponse: + $ref: '#/components/messages/RfqSubmitQuoteResponse' + rfqWithdrawQuoteResponse: + $ref: '#/components/messages/RfqWithdrawQuoteResponse' + rfqConfirmQuoteResponse: + $ref: '#/components/messages/RfqConfirmQuoteResponse' + errorResponse: + $ref: '#/components/messages/ErrorResponse' + bookTicker: + address: "{symbol}@bookTicker" + messages: + bookTicker: + $ref: '#/components/messages/BookTicker' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + depth5: + address: "{symbol}@depth5" + messages: + orderBookSnapshot: + $ref: '#/components/messages/OrderBookSnapshot' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + depth10: + address: "{symbol}@depth10" + messages: + orderBookSnapshot: + $ref: '#/components/messages/OrderBookSnapshot' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + depth20: + address: "{symbol}@depth20" + messages: + orderBookSnapshot: + $ref: '#/components/messages/OrderBookSnapshot' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + depth5Fast: + address: "{symbol}@depth5@100ms" + messages: + orderBookSnapshot: + $ref: '#/components/messages/OrderBookSnapshot' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + depth10Fast: + address: "{symbol}@depth10@100ms" + messages: + orderBookSnapshot: + $ref: '#/components/messages/OrderBookSnapshot' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + depth20Fast: + address: "{symbol}@depth20@100ms" + messages: + orderBookSnapshot: + $ref: '#/components/messages/OrderBookSnapshot' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + depth: + address: "{symbol}@depth" + messages: + depthUpdate: + $ref: '#/components/messages/DepthUpdate' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + depthFast: + address: "{symbol}@depth@100ms" + messages: + depthUpdate: + $ref: '#/components/messages/DepthUpdate' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + trade: + address: "{symbol}@trade" + messages: + trade: + $ref: '#/components/messages/Trade' + parameters: + symbol: + $ref: '#/components/parameters/symbol' + ordersAccount: + address: orders@account + messages: + orderUpdate: + $ref: '#/components/messages/OrderUpdate' + ordersSession: + address: orders@session + messages: + orderUpdate: + $ref: '#/components/messages/OrderUpdate' + balancesAccount: + address: balances@account + messages: + balanceUpdate: + $ref: '#/components/messages/BalanceUpdate' + balancesAccountSnapshot: + address: balances@account@1s + messages: + balanceUpdate: + $ref: '#/components/messages/BalanceUpdate' + positionsAccount: + address: positions@account + messages: + positionReport: + $ref: '#/components/messages/PositionReport' + positionsAccountSnapshot: + address: positions@account@1s + messages: + positionReport: + $ref: '#/components/messages/PositionReport' + contractStatus: + address: contractStatus + messages: + contractStatus: + $ref: '#/components/messages/ContractStatus' + requestForQuote: + address: requestForQuote + messages: + requestForQuote: + $ref: '#/components/messages/RfqPublicEvent' + requestForQuoteAccount: + address: requestForQuote@account + messages: + requestForQuote: + $ref: '#/components/messages/RfqPrivateDelivery' + requestForQuoteSession: + address: requestForQuote@session + messages: + requestForQuote: + $ref: '#/components/messages/RfqPrivateDelivery' +operations: + sendRequests: + action: send + channel: + $ref: '#/channels/connection' + x-gemini-auth: + required: conditional + timing: websocket-upgrade + notes: Public utility methods, public stream subscriptions, and the depth request work without authentication. Order management, combo RFQ quote methods, and subscriptions to authenticated stream names require an already-authenticated WebSocket connection; see each coverage entry's `auth` value. + messages: + - $ref: '#/channels/connection/messages/conninfoRequest' + - $ref: '#/channels/connection/messages/pingRequest' + - $ref: '#/channels/connection/messages/timeRequest' + - $ref: '#/channels/connection/messages/subscribeRequest' + - $ref: '#/channels/connection/messages/unsubscribeRequest' + - $ref: '#/channels/connection/messages/listSubscriptionsRequest' + - $ref: '#/channels/connection/messages/depthRequest' + - $ref: '#/channels/connection/messages/orderPlaceRequest' + - $ref: '#/channels/connection/messages/orderCancelRequest' + - $ref: '#/channels/connection/messages/orderCancelAllRequest' + - $ref: '#/channels/connection/messages/orderCancelSessionRequest' + - $ref: '#/channels/connection/messages/rfqSubmitQuoteRequest' + - $ref: '#/channels/connection/messages/rfqWithdrawQuoteRequest' + - $ref: '#/channels/connection/messages/rfqConfirmQuoteRequest' + receiveResponses: + action: receive + channel: + $ref: '#/channels/connection' + x-gemini-auth: + required: conditional + timing: websocket-upgrade + notes: The response envelope is shared by public and authenticated methods. Authentication requirements are modeled on authenticated request messages and private stream receive operations. + messages: + - $ref: '#/channels/connection/messages/genericSuccessResponse' + - $ref: '#/channels/connection/messages/listSubscriptionsResponse' + - $ref: '#/channels/connection/messages/depthResponse' + - $ref: '#/channels/connection/messages/orderActionResponse' + - $ref: '#/channels/connection/messages/rfqSubmitQuoteResponse' + - $ref: '#/channels/connection/messages/rfqWithdrawQuoteResponse' + - $ref: '#/channels/connection/messages/rfqConfirmQuoteResponse' + - $ref: '#/channels/connection/messages/errorResponse' + receiveBookTicker: + action: receive + channel: + $ref: '#/channels/bookTicker' + messages: + - $ref: '#/channels/bookTicker/messages/bookTicker' + receivePartialDepth: + action: receive + channel: + $ref: '#/channels/depth10' + messages: + - $ref: '#/channels/depth10/messages/orderBookSnapshot' + receivePartialDepth5: + action: receive + channel: + $ref: '#/channels/depth5' + messages: + - $ref: '#/channels/depth5/messages/orderBookSnapshot' + receivePartialDepth20: + action: receive + channel: + $ref: '#/channels/depth20' + messages: + - $ref: '#/channels/depth20/messages/orderBookSnapshot' + receivePartialDepth5Fast: + action: receive + channel: + $ref: '#/channels/depth5Fast' + messages: + - $ref: '#/channels/depth5Fast/messages/orderBookSnapshot' + receivePartialDepth10Fast: + action: receive + channel: + $ref: '#/channels/depth10Fast' + messages: + - $ref: '#/channels/depth10Fast/messages/orderBookSnapshot' + receivePartialDepth20Fast: + action: receive + channel: + $ref: '#/channels/depth20Fast' + messages: + - $ref: '#/channels/depth20Fast/messages/orderBookSnapshot' + receiveDifferentialDepth: + action: receive + channel: + $ref: '#/channels/depthFast' + messages: + - $ref: '#/channels/depthFast/messages/depthUpdate' + receiveDifferentialDepthStandard: + action: receive + channel: + $ref: '#/channels/depth' + messages: + - $ref: '#/channels/depth/messages/depthUpdate' + receiveTrades: + action: receive + channel: + $ref: '#/channels/trade' + messages: + - $ref: '#/channels/trade/messages/trade' + receiveOrderUpdates: + action: receive + channel: + $ref: '#/channels/ordersAccount' + security: + - $ref: '#/components/securitySchemes/geminiApiKeySignature' + - $ref: '#/components/securitySchemes/geminiOAuthBearer' + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + messages: + - $ref: '#/channels/ordersAccount/messages/orderUpdate' + receiveSessionOrderUpdates: + action: receive + channel: + $ref: '#/channels/ordersSession' + security: + - $ref: '#/components/securitySchemes/geminiApiKeySignature' + - $ref: '#/components/securitySchemes/geminiOAuthBearer' + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + messages: + - $ref: '#/channels/ordersSession/messages/orderUpdate' + receiveBalanceUpdates: + action: receive + channel: + $ref: '#/channels/balancesAccount' + security: + - $ref: '#/components/securitySchemes/geminiApiKeySignature' + - $ref: '#/components/securitySchemes/geminiOAuthBearer' + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + messages: + - $ref: '#/channels/balancesAccount/messages/balanceUpdate' + receiveBalanceSnapshots: + action: receive + channel: + $ref: '#/channels/balancesAccountSnapshot' + security: + - $ref: '#/components/securitySchemes/geminiApiKeySignature' + - $ref: '#/components/securitySchemes/geminiOAuthBearer' + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + messages: + - $ref: '#/channels/balancesAccountSnapshot/messages/balanceUpdate' + receivePositionReports: + action: receive + channel: + $ref: '#/channels/positionsAccount' + security: + - $ref: '#/components/securitySchemes/geminiApiKeySignature' + - $ref: '#/components/securitySchemes/geminiOAuthBearer' + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + messages: + - $ref: '#/channels/positionsAccount/messages/positionReport' + receivePositionReportSnapshots: + action: receive + channel: + $ref: '#/channels/positionsAccountSnapshot' + security: + - $ref: '#/components/securitySchemes/geminiApiKeySignature' + - $ref: '#/components/securitySchemes/geminiOAuthBearer' + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + messages: + - $ref: '#/channels/positionsAccountSnapshot/messages/positionReport' + receiveContractStatus: + action: receive + channel: + $ref: '#/channels/contractStatus' + messages: + - $ref: '#/channels/contractStatus/messages/contractStatus' + receiveRfqPublicEvents: + action: receive + channel: + $ref: '#/channels/requestForQuote' + messages: + - $ref: '#/channels/requestForQuote/messages/requestForQuote' + receiveRfqPrivateDeliveries: + action: receive + channel: + $ref: '#/channels/requestForQuoteAccount' + security: + - $ref: '#/components/securitySchemes/geminiApiKeySignature' + - $ref: '#/components/securitySchemes/geminiOAuthBearer' + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + capabilities: [view_orders] + messages: + - $ref: '#/channels/requestForQuoteAccount/messages/requestForQuote' + receiveRfqSessionDeliveries: + action: receive + channel: + $ref: '#/channels/requestForQuoteSession' + security: + - $ref: '#/components/securitySchemes/geminiApiKeySignature' + - $ref: '#/components/securitySchemes/geminiOAuthBearer' + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + capabilities: [view_orders] + messages: + - $ref: '#/channels/requestForQuoteSession/messages/requestForQuote' +components: + securitySchemes: + geminiApiKeySignature: + type: httpApiKey + name: X-GEMINI-APIKEY + in: header + description: | + Account-scoped Gemini API key supplied during the WebSocket upgrade. + This scheme represents the full Gemini HMAC-signed header set. A valid + handshake also includes `X-GEMINI-NONCE`, `X-GEMINI-PAYLOAD`, and + `X-GEMINI-SIGNATURE`; `X-GEMINI-PAYLOAD` is `base64(string(nonce))`, + and `X-GEMINI-SIGNATURE` is `hex(hmac_sha384(payload, api_secret))`. + Only account-scoped keys with time-based nonces are accepted; master or + group keys are rejected with HTTP 401. + x-gemini-required-headers: + - X-GEMINI-APIKEY + - X-GEMINI-NONCE + - X-GEMINI-PAYLOAD + - X-GEMINI-SIGNATURE + x-gemini-key-scope: account + x-gemini-nonce: time-based + x-gemini-signature-algorithm: HMAC-SHA384 + geminiOAuthBearer: + type: http + scheme: bearer + bearerFormat: Gemini OAuth 2.0 access token + description: | + OAuth 2.0 access token supplied as `Authorization: Bearer ` + during the WebSocket upgrade. The token must include scopes/capabilities + for the private streams or methods used on the connection. + parameters: + symbol: + description: | + Exchange symbol. For trading markets this may be a symbol like `btcusd`. + For prediction markets this is an instrument symbol such as + `GEMI-BTC05M2606011000-UP`. + messages: + ConninfoRequest: + name: ConninfoRequest + title: conninfo request + payload: + $ref: '#/components/schemas/ConninfoRequest' + PingRequest: + name: PingRequest + title: ping request + payload: + $ref: '#/components/schemas/PingRequest' + TimeRequest: + name: TimeRequest + title: time request + payload: + $ref: '#/components/schemas/TimeRequest' + SubscribeRequest: + name: SubscribeRequest + title: subscribe request + payload: + $ref: '#/components/schemas/SubscribeRequest' + UnsubscribeRequest: + name: UnsubscribeRequest + title: unsubscribe request + payload: + $ref: '#/components/schemas/UnsubscribeRequest' + ListSubscriptionsRequest: + name: ListSubscriptionsRequest + title: list subscriptions request + payload: + $ref: '#/components/schemas/ListSubscriptionsRequest' + DepthRequest: + name: DepthRequest + title: depth request + payload: + $ref: '#/components/schemas/DepthRequest' + OrderPlaceRequest: + name: OrderPlaceRequest + title: order.place request + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + roles: [Trader] + payload: + $ref: '#/components/schemas/OrderPlaceRequest' + OrderCancelRequest: + name: OrderCancelRequest + title: order.cancel request + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + roles: [Trader] + payload: + $ref: '#/components/schemas/OrderCancelRequest' + OrderCancelAllRequest: + name: OrderCancelAllRequest + title: order.cancel_all request + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + roles: [Trader] + payload: + $ref: '#/components/schemas/OrderCancelAllRequest' + OrderCancelSessionRequest: + name: OrderCancelSessionRequest + title: order.cancel_session request + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + roles: [Trader] + payload: + $ref: '#/components/schemas/OrderCancelSessionRequest' + RfqSubmitQuoteRequest: + name: RfqSubmitQuoteRequest + title: rfq.submit_quote request + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + capabilities: [place_orders] + payload: + $ref: '#/components/schemas/RfqSubmitQuoteRequest' + RfqWithdrawQuoteRequest: + name: RfqWithdrawQuoteRequest + title: rfq.withdraw_quote request + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + capabilities: [cancel_orders] + payload: + $ref: '#/components/schemas/RfqWithdrawQuoteRequest' + RfqConfirmQuoteRequest: + name: RfqConfirmQuoteRequest + title: rfq.confirm_quote request + x-gemini-auth: + required: true + timing: websocket-upgrade + alternatives: [geminiApiKeySignature, geminiOAuthBearer] + capabilities: [place_orders] + payload: + $ref: '#/components/schemas/RfqConfirmQuoteRequest' + GenericSuccessResponse: + name: GenericSuccessResponse + title: generic success response + payload: + $ref: '#/components/schemas/GenericSuccessResponse' + ListSubscriptionsResponse: + name: ListSubscriptionsResponse + title: list subscriptions response + payload: + $ref: '#/components/schemas/ListSubscriptionsResponse' + DepthResponse: + name: DepthResponse + title: depth response + payload: + $ref: '#/components/schemas/DepthResponse' + OrderActionResponse: + name: OrderActionResponse + title: order action response + payload: + $ref: '#/components/schemas/OrderActionResponse' + RfqSubmitQuoteResponse: + name: RfqSubmitQuoteResponse + title: rfq.submit_quote response + payload: + $ref: '#/components/schemas/RfqSubmitQuoteResponse' + RfqWithdrawQuoteResponse: + name: RfqWithdrawQuoteResponse + title: rfq.withdraw_quote response + payload: + $ref: '#/components/schemas/RfqWithdrawQuoteResponse' + RfqConfirmQuoteResponse: + name: RfqConfirmQuoteResponse + title: rfq.confirm_quote response + payload: + $ref: '#/components/schemas/RfqConfirmQuoteResponse' + ErrorResponse: + name: ErrorResponse + title: error response + payload: + $ref: '#/components/schemas/ErrorResponse' + BookTicker: + name: BookTicker + title: book ticker + payload: + $ref: '#/components/schemas/BookTicker' + OrderBookSnapshot: + name: OrderBookSnapshot + title: order book snapshot + payload: + $ref: '#/components/schemas/OrderBookSnapshot' + DepthUpdate: + name: DepthUpdate + title: L2 differential depth update + payload: + $ref: '#/components/schemas/DepthUpdate' + Trade: + name: Trade + title: trade + payload: + $ref: '#/components/schemas/Trade' + OrderUpdate: + name: OrderUpdate + title: order update + payload: + $ref: '#/components/schemas/OrderUpdate' + BalanceUpdate: + name: BalanceUpdate + title: balance update + payload: + $ref: '#/components/schemas/BalanceUpdate' + PositionReport: + name: PositionReport + title: position report + payload: + $ref: '#/components/schemas/PositionReport' + ContractStatus: + name: ContractStatus + title: contract status + payload: + $ref: '#/components/schemas/ContractStatus' + RfqPublicEvent: + name: RfqPublicEvent + title: public request-for-quote event + payload: + $ref: '#/components/schemas/RfqPublicEvent' + RfqPrivateDelivery: + name: RfqPrivateDelivery + title: private request-for-quote delivery + payload: + $ref: '#/components/schemas/RfqPrivateDelivery' + schemas: + CorrelationId: + description: Client-chosen id, echoed on the matching response. + oneOf: + - type: string + - type: integer + NanosecondTimestamp: + type: integer + format: int64 + description: | + Unix timestamp in nanoseconds. Values exceed JavaScript's safe integer + range; JavaScript clients that need exact values should parse + losslessly. + MillisecondTimestamp: + type: integer + format: int64 + description: Unix timestamp in milliseconds. + DecimalString: + type: string + description: Decimal value encoded as a string. + PriceLevel: + type: array + description: | + `[price, quantity]` tuple; both values are decimal strings. A quantity + of zero removes that price level in differential depth updates. + items: + type: string + minItems: 2 + maxItems: 2 + RequestBase: + type: object + required: [id, method] + properties: + id: + $ref: '#/components/schemas/CorrelationId' + method: + type: string + additionalProperties: true + ConninfoRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method] + properties: + method: + type: string + const: conninfo + params: + type: object + additionalProperties: true + PingRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method] + properties: + method: + type: string + const: ping + params: + type: object + additionalProperties: true + TimeRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method] + properties: + method: + type: string + const: time + params: + type: object + additionalProperties: true + SubscribeRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method, params] + properties: + method: + type: string + pattern: ^(SUBSCRIBE|subscribe)$ + description: | + `SUBSCRIBE` for Prediction Markets docs; lowercase `subscribe` + is also accepted by the shared Trading WebSocket docs. + params: + type: array + description: Stream names to subscribe to. + items: + type: string + UnsubscribeRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method, params] + properties: + method: + type: string + pattern: ^(UNSUBSCRIBE|unsubscribe)$ + description: | + `UNSUBSCRIBE` for Prediction Markets docs; lowercase + `unsubscribe` is also accepted by the shared Trading WebSocket + docs. + params: + type: array + description: Stream names to unsubscribe from. + items: + type: string + ListSubscriptionsRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method] + properties: + method: + type: string + pattern: ^(LIST_SUBSCRIPTIONS|list_subscriptions)$ + description: | + `LIST_SUBSCRIPTIONS` for Prediction Markets docs; lowercase + `list_subscriptions` is also accepted by the shared Trading + WebSocket docs. + params: + type: object + additionalProperties: true + DepthRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method, params] + properties: + method: + type: string + const: depth + params: + type: object + required: [symbol] + properties: + symbol: + type: string + limit: + type: integer + minimum: 1 + maximum: 5000 + default: 100 + additionalProperties: true + OrderPlaceRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method, params] + properties: + method: + type: string + const: order.place + params: + $ref: '#/components/schemas/OrderPlaceParams' + OrderCancelRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method, params] + properties: + method: + type: string + const: order.cancel + params: + $ref: '#/components/schemas/OrderCancelParams' + OrderCancelAllRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method] + properties: + method: + type: string + const: order.cancel_all + params: + type: object + additionalProperties: true + OrderCancelSessionRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method] + properties: + method: + type: string + const: order.cancel_session + params: + type: object + additionalProperties: true + RfqSubmitQuoteRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method, params] + properties: + method: + type: string + const: rfq.submit_quote + params: + $ref: '#/components/schemas/RfqSubmitQuoteParams' + RfqWithdrawQuoteRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method, params] + properties: + method: + type: string + const: rfq.withdraw_quote + params: + $ref: '#/components/schemas/RfqWithdrawQuoteParams' + RfqConfirmQuoteRequest: + allOf: + - $ref: '#/components/schemas/RequestBase' + - type: object + required: [method, params] + properties: + method: + type: string + const: rfq.confirm_quote + params: + $ref: '#/components/schemas/RfqConfirmQuoteParams' + ResponseBase: + type: object + required: [id, status] + properties: + id: + $ref: '#/components/schemas/CorrelationId' + status: + type: integer + description: HTTP-style status code. + additionalProperties: true + GenericSuccessResponse: + allOf: + - $ref: '#/components/schemas/ResponseBase' + - type: object + properties: + result: + description: Method-specific result. Some utility result fields are not enumerated in the docs. + ListSubscriptionsResponse: + allOf: + - $ref: '#/components/schemas/ResponseBase' + - type: object + properties: + result: + type: array + items: + type: string + DepthResponse: + allOf: + - $ref: '#/components/schemas/ResponseBase' + - type: object + properties: + result: + $ref: '#/components/schemas/OrderBookSnapshot' + OrderActionResponse: + allOf: + - $ref: '#/components/schemas/ResponseBase' + - type: object + properties: + result: + type: object + description: | + Method-specific order result. Order lifecycle state is carried + authoritatively on the `orderUpdate` stream. + additionalProperties: true + RfqSubmitQuoteResponse: + allOf: + - $ref: '#/components/schemas/ResponseBase' + - type: object + properties: + result: + type: object + required: [rfqId, quoteId] + properties: + rfqId: + type: string + quoteId: + type: string + additionalProperties: true + RfqWithdrawQuoteResponse: + allOf: + - $ref: '#/components/schemas/ResponseBase' + - type: object + properties: + result: + type: object + required: [rfqId, quoteId] + properties: + rfqId: + type: string + quoteId: + type: string + additionalProperties: true + RfqConfirmQuoteResponse: + allOf: + - $ref: '#/components/schemas/ResponseBase' + - type: object + properties: + result: + type: object + required: [rfqId, quoteId, confirmed] + properties: + rfqId: + type: string + quoteId: + type: string + confirmed: + type: boolean + additionalProperties: true + ErrorResponse: + allOf: + - $ref: '#/components/schemas/ResponseBase' + - type: object + required: [error] + properties: + error: + $ref: '#/components/schemas/WsError' + WsError: + type: object + required: [code, msg] + properties: + code: + type: integer + description: Internal error code, e.g. -1002. + msg: + type: string + description: Human-readable error message. + additionalProperties: true + OrderPlaceParams: + type: object + required: [symbol, side, type, timeInForce, quantity] + properties: + symbol: + type: string + side: + type: string + enum: [BUY, SELL] + type: + type: string + enum: [LIMIT, MARKET] + description: Use LIMIT with price and stopPrice for a stop-limit order. For this WebSocket contract, BUY stopPrice may be equal to or below price and SELL stopPrice may be equal to or above price. The order event reports its type as STOP_LIMIT. The legacy REST order endpoint has separate strict inequality rules. + timeInForce: + type: string + enum: [GTC, IOC, FOK, MOC] + price: + $ref: '#/components/schemas/DecimalString' + stopPrice: + $ref: '#/components/schemas/DecimalString' + quantity: + $ref: '#/components/schemas/DecimalString' + clientOrderId: + type: string + eventOutcome: + type: string + enum: [YES, NO] + description: Required for prediction market event contracts. + additionalProperties: true + OrderCancelParams: + type: object + required: [orderId] + properties: + orderId: + oneOf: + - type: string + - type: integer + additionalProperties: true + OrderBookSnapshot: + type: object + description: Snapshot payload used by partial depth streams and the `depth` method. + required: [lastUpdateId, bids, asks] + properties: + lastUpdateId: + type: integer + format: int64 + bids: + type: array + items: + $ref: '#/components/schemas/PriceLevel' + asks: + type: array + items: + $ref: '#/components/schemas/PriceLevel' + additionalProperties: true + BookTicker: + type: object + required: [u, E, s, b, B, a, A] + properties: + u: + type: integer + format: int64 + description: Update ID. + E: + $ref: '#/components/schemas/NanosecondTimestamp' + s: + type: string + b: + $ref: '#/components/schemas/DecimalString' + B: + $ref: '#/components/schemas/DecimalString' + a: + $ref: '#/components/schemas/DecimalString' + A: + $ref: '#/components/schemas/DecimalString' + c: + $ref: '#/components/schemas/DecimalString' + description: Last trade price, present once the book has traded. + C: + $ref: '#/components/schemas/DecimalString' + description: Last trade size, present once the book has traded. + additionalProperties: true + DepthUpdate: + type: object + description: > + L2 depth frame. With the `snapshot` connection parameter set — `-1` for the + full book, a positive N for the top N levels — the FIRST frame after + subscribing is the snapshot (b/a hold absolute levels, and U..u identifies + the update range covered by the frame); every frame after it is an incremental + diff. There is no separate snapshot message and no lastUpdateId field. Apply + frames in order, using u as the last applied update ID; if a frame's U skips + ahead of the last applied u, discard the book and resubscribe to resync. + required: [e, E, s, U, u, b, a] + properties: + e: + type: string + const: depthUpdate + E: + $ref: '#/components/schemas/NanosecondTimestamp' + s: + type: string + U: + type: integer + format: int64 + u: + type: integer + format: int64 + b: + type: array + items: + $ref: '#/components/schemas/PriceLevel' + a: + type: array + items: + $ref: '#/components/schemas/PriceLevel' + additionalProperties: true + Trade: + type: object + required: [E, s, t, p, q, m] + properties: + E: + $ref: '#/components/schemas/NanosecondTimestamp' + s: + type: string + t: + type: integer + format: int64 + p: + $ref: '#/components/schemas/DecimalString' + q: + $ref: '#/components/schemas/DecimalString' + m: + type: boolean + description: Whether the buyer is the maker. + additionalProperties: true + OrderUpdate: + type: object + description: | + Authenticated order lifecycle event. Fields with empty or zero values may + be omitted from the event. + required: [e, E, s, i, X, T] + properties: + e: + type: string + const: orderUpdate + E: + $ref: '#/components/schemas/NanosecondTimestamp' + s: + type: string + i: + type: integer + format: int64 + c: + type: string + description: Client order ID. For RFQ maker fills, this is the clientId supplied to rfq.submit_quote, or Gemini's deterministic RFQ client order ID when clientId is omitted. + S: + type: string + enum: [BUY, SELL] + o: + type: string + enum: [LIMIT, MARKET, STOP_LIMIT, STOP_MARKET] + X: + type: string + enum: [NEW, OPEN, FILLED, PARTIALLY_FILLED, CANCELED, REJECTED, MODIFIED] + O: + type: string + enum: [YES, NO] + description: Event outcome for prediction market contracts. + p: + $ref: '#/components/schemas/DecimalString' + P: + $ref: '#/components/schemas/DecimalString' + description: Stop price, `0` when not a stop order. + q: + $ref: '#/components/schemas/DecimalString' + z: + $ref: '#/components/schemas/DecimalString' + description: Remaining quantity. + Z: + $ref: '#/components/schemas/DecimalString' + description: | + Executed quantity. For `FILLED` / `PARTIALLY_FILLED`, this is the + last execution quantity. For `CANCELED` and other events, this is + cumulative executed quantity over the order lifetime. + L: + $ref: '#/components/schemas/DecimalString' + t: + type: integer + format: int64 + n: + $ref: '#/components/schemas/DecimalString' + description: Fee amount, only present on fill events. + m: + type: boolean + description: Maker flag on fills. + r: + type: string + description: Rejection or cancellation reason. + T: + $ref: '#/components/schemas/NanosecondTimestamp' + additionalProperties: true + BalanceUpdate: + type: object + required: [e, E, u, B] + properties: + e: + type: string + const: balanceUpdate + E: + $ref: '#/components/schemas/NanosecondTimestamp' + u: + $ref: '#/components/schemas/NanosecondTimestamp' + B: + type: array + items: + $ref: '#/components/schemas/Balance' + additionalProperties: true + Balance: + type: object + required: [a, f, c] + properties: + a: + type: string + description: Asset code. + f: + $ref: '#/components/schemas/DecimalString' + c: + $ref: '#/components/schemas/DecimalString' + additionalProperties: true + PositionReport: + type: object + required: [e, E, u, A, P] + properties: + e: + type: string + const: positionReport + E: + $ref: '#/components/schemas/NanosecondTimestamp' + u: + $ref: '#/components/schemas/NanosecondTimestamp' + A: + type: integer + format: int64 + description: Account ID. + P: + type: array + items: + $ref: '#/components/schemas/PositionRow' + additionalProperties: true + PositionRow: + type: object + required: [t, s, a] + properties: + t: + type: string + description: Product type; event contracts use `ec`. + s: + type: string + a: + type: array + items: + $ref: '#/components/schemas/NamedAmount' + additionalProperties: true + NamedAmount: + type: object + required: [t, v] + properties: + t: + type: string + description: Amount label, such as `position` or `settlement_payout`. + v: + $ref: '#/components/schemas/DecimalString' + description: Decimal amount. The `position` amount is a signed quantity; `settlement_payout` is the settlement payout. + c: + type: string + description: Optional asset code, such as `usd` for settlement payouts. + o: + type: string + enum: [YES, NO, UNSPECIFIED] + description: Settlement outcome. Present on `settlement_payout` amounts in terminal event-contract position rows. + additionalProperties: true + ContractStatus: + type: object + required: [e, E, s, k, c, i, o, n] + properties: + e: + type: string + const: contractStatus + E: + $ref: '#/components/schemas/MillisecondTimestamp' + s: + type: string + k: + type: string + description: Event ticker. + c: + type: string + description: Contract ticker. + i: + type: integer + format: int64 + p: + $ref: '#/components/schemas/DecimalString' + description: Strike price, omitted for Up/Down contracts until populated. + o: + type: string + description: Previous status. + n: + type: string + description: New status. + additionalProperties: true + RfqClientId: + type: string + description: Optional client order ID for tracking the maker fill. It is emitted as the fill event's c field. It must contain only printable ASCII characters and be at most 36 characters. Keep it unique for the maker account because the venue does not deduplicate it. + RfqSubmitQuoteParams: + type: object + required: [rfqId, price, quantity] + properties: + rfqId: + type: string + price: + $ref: '#/components/schemas/DecimalString' + quantity: + $ref: '#/components/schemas/DecimalString' + validUntil: + $ref: '#/components/schemas/MillisecondTimestamp' + clientId: + $ref: '#/components/schemas/RfqClientId' + additionalProperties: true + RfqWithdrawQuoteParams: + type: object + required: [rfqId, quoteId] + properties: + rfqId: + type: string + quoteId: + type: string + additionalProperties: true + RfqConfirmQuoteParams: + type: object + required: [rfqId, quoteId, confirm] + properties: + rfqId: + type: string + quoteId: + type: string + confirm: + type: boolean + additionalProperties: true + RfqLeg: + type: object + required: [c, o] + properties: + c: + type: string + description: CMS contract id. + o: + type: string + enum: [YES, NO] + s: + type: string + description: This leg's own instrument symbol, when available. Distinct from the combo-level `s` on the enclosing event. + example: "GEMI-XRPUSD-260828" + additionalProperties: true + RfqLifecycleState: + type: string + enum: [OPEN, PENDING_ACCEPTANCE, CONFIRMING, FINALIZING, FINALIZED, CANCELLED, EXPIRED, FAILED] + RfqQuoteStatus: + type: string + enum: [ACTIVE, WITHDRAWN, EXPIRED, WON, LOST] + RfqPublicEvent: + type: object + required: [e, E, r, l, S] + properties: + e: + type: string + const: requestForQuote + E: + $ref: '#/components/schemas/MillisecondTimestamp' + r: + type: string + description: RFQ ID. + s: + type: string + description: The combo's deterministic instrument symbol, when available. Market makers can use it to place a CLOB order on the combo, activating its book on demand. + l: + type: array + items: + $ref: '#/components/schemas/RfqLeg' + n: + $ref: '#/components/schemas/DecimalString' + description: Requested notional size, mutually exclusive with `q`. + q: + $ref: '#/components/schemas/DecimalString' + description: Requested contract quantity, mutually exclusive with `n`. The RFQ quantity grid can be whole contracts or 0.01 fractional contracts. + f: + $ref: '#/components/schemas/DecimalString' + description: Execution quantity calculated when the requester accepts. + S: + $ref: '#/components/schemas/RfqLifecycleState' + w: + $ref: '#/components/schemas/MillisecondTimestamp' + x: + $ref: '#/components/schemas/MillisecondTimestamp' + c: + $ref: '#/components/schemas/MillisecondTimestamp' + additionalProperties: true + RfqPrivateDelivery: + type: object + required: [e, i, E, r, x, S] + properties: + e: + type: string + const: requestForQuote + i: + type: string + description: Durable lifecycle-event UUID for at-least-once deduplication. + E: + $ref: '#/components/schemas/MillisecondTimestamp' + r: + type: string + description: RFQ ID. + x: + type: string + enum: [CLOSED, ACCEPTED, CONFIRMED, DECLINED, FINALIZED, FAILED] + description: Customer-visible lifecycle transition. + S: + $ref: '#/components/schemas/RfqLifecycleState' + q: + type: string + description: Quote ID on authenticated delivery streams. + p: + $ref: '#/components/schemas/DecimalString' + sz: + $ref: '#/components/schemas/DecimalString' + qs: + $ref: '#/components/schemas/RfqQuoteStatus' + vu: + $ref: '#/components/schemas/MillisecondTimestamp' + additionalProperties: true diff --git a/specs/openapi/prediction-markets.yaml b/specs/openapi/prediction-markets.yaml new file mode 100644 index 00000000..f07ca89b --- /dev/null +++ b/specs/openapi/prediction-markets.yaml @@ -0,0 +1,5188 @@ +openapi: 3.0.3 +info: + title: Gemini Prediction Markets API + description: | + API for trading prediction market contracts on Gemini. + + **Note:** Only fields documented in this specification are considered stable. Undocumented fields in API responses may change or be removed without notice. + version: 1.0.0 + contact: + name: Gemini API Support + +servers: + - url: https://api.gemini.com + description: Production + - url: https://api.sandbox.gemini.com + description: Sandbox + +tags: + - name: Markets + description: | + Public endpoints for browsing prediction markets. + + **Market Data:** Use these REST endpoints to discover active events and each contract's `instrumentSymbol` (e.g., `GEMI-FEDJAN26-DN25`). For active trading and market making, prefer [Prediction Markets WebSocket streams](/prediction-markets/websocket/streams) with that `instrumentSymbol`. + - [List Events](/rest-api/prediction-markets/events/list-events) - Discover active events and instrument symbols + - [Prediction Markets WebSocket Streams](/prediction-markets/websocket/streams) - Stream prices, depth, order events, and positions + - name: Volume + description: Public, unauthenticated prediction-market trade volume by category and UTC period. + - name: Terms + description: Read, check, and accept the latest Prediction Markets terms for API key and OAuth trading flows. + - name: Trading + description: Authenticated REST endpoints for placing and managing orders. Treat REST order placement as payload reference or a one-off server workflow; for active trading and market making, prefer WebSocket order.place. + - name: Positions + description: Authenticated endpoints for viewing positions and order history. Use REST positions for recovery or audit snapshots after reconnects, missed WebSocket messages, and settlement windows. + - name: Combos + description: Public endpoints for discovering and inspecting combo contracts, plus an authenticated endpoint to create or retrieve a canonical combo. Combos are multi-leg contracts; order entry uses the same place/cancel endpoints as single contracts. + - name: Rewards + description: | + Endpoints for the Maker Rebate and Liquidity Rewards programs. + + - **Maker Rebate** — per-fill rebates earned by resting limit orders that get filled. Rates and rebate multipliers are configured per category. Public rate schedule plus authenticated payout and summary endpoints. + - **Liquidity Rewards** — daily USD reward pools distributed across qualifying makers based on quote uptime, spread, and size. Public config + event listing, authenticated daily and lifetime summary endpoints. + + When a program is not active, its endpoints return `503 Service Unavailable`. + + **Note on field naming.** Response fields under the Rewards endpoints use `snake_case` (e.g. `event_ticker`, `daily_pool_usd`). This differs from the `camelCase` convention used by the rest of the Prediction Markets REST endpoints. + +paths: + /v1/prediction-markets/events: + get: + tags: + - Markets + summary: List prediction market events + description: Returns a paginated list of prediction market events with optional filtering by status, category, sports-market classification, and search text. Repeated values for the same filter use OR semantics; different filters combine with AND semantics. + operationId: listEvents + parameters: + - name: status + in: query + description: Filter by event status (can specify multiple) + schema: + type: array + items: + $ref: '#/components/schemas/MarketStatus' + style: form + explode: true + - name: category + in: query + description: Filter by category (can specify multiple). If omitted, returns events from all categories. + schema: + type: array + items: + type: string + style: form + explode: true + - $ref: '#/components/parameters/SportFilter' + - $ref: '#/components/parameters/SportsMarketTypeFilter' + - $ref: '#/components/parameters/SportsMarketSubjectFilter' + - $ref: '#/components/parameters/SportsMarketScopeFilter' + - $ref: '#/components/parameters/SportsMarketMetricFilter' + - name: search + in: query + description: Search text to filter events by title + schema: + type: string + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Offset' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/EventsResponse' + examples: + activeEvents: + summary: List of active events + value: + data: + - id: "evt_123" + title: "Will Bitcoin reach $100k by end of 2028?" + slug: "bitcoin-100k-2028" + description: "Bitcoin must reach $100,000 USD on any major exchange by December 31, 2028" + imageUrl: "https://example.com/btc.png" + type: "binary" + category: "crypto" + series: null + ticker: "BTC100K2028" + status: "active" + resolvedAt: null + createdAt: "2026-01-01T00:00:00.000Z" + effectiveDate: "2026-01-01T00:00:00.000Z" + expiryDate: "2028-12-31T23:59:59.000Z" + liquidity: "500000.00" + tags: ["bitcoin", "cryptocurrency", "price-prediction"] + contracts: + - id: "contract_123" + label: "BTC reaches $100,000 by end of 2028" + description: null + prices: + buy: + "yes": "0.65" + "no": "0.35" + sell: + "yes": "0.65" + "no": "0.35" + bestBid: "0.64" + bestAsk: "0.66" + lastTradePrice: "0.65" + color: "#00ff00" + status: "active" + imageUrl: null + priceHistory: null + createdAt: "2026-01-01T00:00:00.000Z" + expiryDate: "2028-12-31T23:59:59.000Z" + resolutionSide: null + resolvedAt: null + termsAndConditionsUrl: "https://example.com/terms" + ticker: "BTC100K2028" + instrumentSymbol: "GEMI-BTC100K2028" + effectiveDate: "2026-01-01T00:00:00.000Z" + - id: "evt_124" + title: "Will ETH reach $5k by end of 2028?" + slug: "ethereum-5k-2028" + description: "Ethereum must reach $5,000 USD on any major exchange by December 31, 2028" + imageUrl: "https://example.com/eth.png" + type: "binary" + category: "crypto" + series: null + ticker: "ETH5K2028" + status: "active" + resolvedAt: null + createdAt: "2026-01-01T00:00:00.000Z" + effectiveDate: "2026-01-01T00:00:00.000Z" + expiryDate: "2028-12-31T23:59:59.000Z" + liquidity: "300000.00" + tags: ["ethereum", "cryptocurrency", "price-prediction"] + contracts: + - id: "contract_125" + label: "ETH reaches $5,000 by end of 2028" + description: null + prices: + buy: + "yes": "0.48" + "no": "0.52" + sell: + "yes": "0.48" + "no": "0.52" + bestBid: "0.47" + bestAsk: "0.49" + lastTradePrice: "0.48" + color: "#00ff00" + status: "active" + imageUrl: null + priceHistory: null + createdAt: "2026-01-01T00:00:00.000Z" + expiryDate: "2028-12-31T23:59:59.000Z" + resolutionSide: null + resolvedAt: null + termsAndConditionsUrl: "https://example.com/terms" + ticker: "ETH5K2028" + instrumentSymbol: "GEMI-ETH5K2028" + effectiveDate: "2026-01-01T00:00:00.000Z" + pagination: + limit: 50 + offset: 0 + total: 2 + sportsMarkets: + summary: Sports markets across leagues and periods + value: + data: + - id: "evt_mlb_first_five_spread" + title: "Yankees at Red Sox - First 5 Innings Spread" + type: "binary" + category: "Sports" + sportsMarket: + sport: "baseball" + type: "spread" + subject: "team" + scope: + type: "inning" + start: 1 + end: 5 + metric: "runs" + contracts: [] + - id: "evt_nfl_first_half_spread" + title: "Bills at Chiefs - First Half Spread" + type: "binary" + category: "Sports" + sportsMarket: + sport: "american_football" + type: "spread" + subject: "team" + scope: + type: "half" + ordinal: 1 + metric: "points" + contracts: [] + - id: "evt_ncaaf_team_total" + title: "Michigan Team Total vs Ohio State" + type: "binary" + category: "Sports" + sportsMarket: + sport: "american_football" + type: "total" + subject: "team" + scope: + type: "full_contest" + metric: "points" + contracts: [] + pagination: + limit: 50 + offset: 0 + total: 3 + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/events/{eventTicker}: + get: + tags: + - Markets + summary: Get event by ticker + description: Returns detailed information about a specific prediction market event. + operationId: getEvent + parameters: + - name: eventTicker + in: path + required: true + description: The event ticker symbol (e.g., "BTC100K") + schema: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/Event' + '404': + description: Event not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/events/{eventTicker}/strike: + get: + tags: + - Markets + summary: Get strike price for event + description: | + Returns strike price information for a specific prediction market event. + + Useful for crypto Up/Down contracts where the strike price becomes available at the start of the observation window (typically ~5 minutes before expiry for 5M contracts). + + For Up/Down contracts, the `value` field will be `null` until the strike is captured at `availableAt` time. + operationId: getEventStrike + parameters: + - name: eventTicker + in: path + required: true + description: The event ticker symbol (e.g., "BTC05M2603271950") + schema: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/Strike' + examples: + strikeAvailable: + summary: Strike price captured + value: + value: "98000.50" + type: "reference" + availableAt: "2026-03-27T19:45:00.000Z" + strikePending: + summary: Strike pending (pre-T-0) + value: + value: null + type: "reference" + availableAt: "2026-03-27T19:45:00.000Z" + '404': + description: Strike not found (event doesn't exist or doesn't have strike data) + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "Strike not found" + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/events/newly-listed: + get: + tags: + - Markets + summary: List newly listed events + description: Returns a list of prediction market events created in the last 24 hours, sorted by creation date (newest first). Repeated values for the same sports-market filter use OR semantics; different filters combine with AND semantics. + operationId: listNewlyListedEvents + parameters: + - name: category + in: query + description: Filter by category (can specify multiple). If omitted, returns events from all categories. + schema: + type: array + items: + type: string + style: form + explode: true + - $ref: '#/components/parameters/SportFilter' + - $ref: '#/components/parameters/SportsMarketTypeFilter' + - $ref: '#/components/parameters/SportsMarketSubjectFilter' + - $ref: '#/components/parameters/SportsMarketScopeFilter' + - $ref: '#/components/parameters/SportsMarketMetricFilter' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Offset' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/EventsResponse' + examples: + newlyListedEvents: + summary: Newly listed events + value: + data: + - id: "4126" + title: "SOL price today at 12am EST" + slug: "sol-price-today-at-12am-est" + description: "Interval SOL price prediction event" + imageUrl: "https://images.ctfassets.net/example.png" + type: "categorical" + category: "Crypto" + series: "SOL1H" + ticker: "SOL2603050500" + status: "active" + resolvedAt: null + createdAt: "2026-03-05T02:57:31.548Z" + effectiveDate: null + expiryDate: "2026-03-05T05:00:00.000Z" + liquidity: null + tags: ["Solana"] + contracts: + - id: "4126-33859" + label: "SOL > $90" + abbreviatedName: ">$90" + description: null + prices: + buy: + "yes": "0.42" + "no": "0.58" + sell: + "yes": "0.42" + "no": "0.58" + bestBid: "0.49" + bestAsk: "0.54" + lastTradePrice: "0.75" + color: "#4CAF50" + status: "active" + imageUrl: null + priceHistory: null + createdAt: "2026-03-05T02:57:31.548Z" + expiryDate: "2026-03-05T05:00:00.000Z" + resolutionSide: null + resolvedAt: null + termsAndConditionsUrl: "https://example.com/terms" + ticker: "HI90" + instrumentSymbol: "GEMI-SOL2603050500-HI90" + effectiveDate: null + marketState: "open" + sortOrder: 1 + pagination: + limit: 50 + offset: 0 + total: 1 + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/events/recently-settled: + get: + tags: + - Markets + summary: List recently settled events + description: Returns a list of prediction market events settled in the last 24 hours, sorted by resolution date (most recently settled first). Repeated values for the same sports-market filter use OR semantics; different filters combine with AND semantics. + operationId: listRecentlySettledEvents + parameters: + - name: category + in: query + description: Filter by category (can specify multiple). If omitted, returns events from all categories. + schema: + type: array + items: + type: string + style: form + explode: true + - $ref: '#/components/parameters/SportFilter' + - $ref: '#/components/parameters/SportsMarketTypeFilter' + - $ref: '#/components/parameters/SportsMarketSubjectFilter' + - $ref: '#/components/parameters/SportsMarketScopeFilter' + - $ref: '#/components/parameters/SportsMarketMetricFilter' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Offset' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/EventsResponse' + examples: + recentlySettledEvents: + summary: Recently settled events + value: + data: + - id: "4100" + title: "SOL price today at 4am EST" + slug: "sol-price-today-at-4am-est" + description: "Interval SOL price prediction event" + imageUrl: "https://images.ctfassets.net/example.png" + type: "categorical" + category: "Crypto" + series: "SOL1H" + ticker: "SOL2603050400" + status: "settled" + resolvedAt: "2026-03-05T04:00:21.400Z" + createdAt: "2026-03-05T01:57:31.548Z" + effectiveDate: null + expiryDate: "2026-03-05T04:00:00.000Z" + liquidity: null + tags: ["Solana"] + contracts: + - id: "4100-33800" + label: "SOL > $90" + abbreviatedName: ">$90" + description: null + prices: + buy: {} + sell: {} + bestBid: null + bestAsk: null + lastTradePrice: "0.80" + color: "#4CAF50" + status: "settled" + imageUrl: null + priceHistory: null + createdAt: "2026-03-05T01:57:31.548Z" + expiryDate: "2026-03-05T04:00:00.000Z" + resolutionSide: "yes" + resolvedAt: "2026-03-05T04:00:21.400Z" + termsAndConditionsUrl: "https://example.com/terms" + ticker: "HI90" + instrumentSymbol: "GEMI-SOL2603050400-HI90" + effectiveDate: null + marketState: "closed" + sortOrder: 1 + pagination: + limit: 50 + offset: 0 + total: 1 + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/events/upcoming: + get: + tags: + - Markets + summary: List upcoming events + description: Returns a list of approved prediction market events that are not yet active (pre-launch), sorted by start time (soonest first). Repeated values for the same sports-market filter use OR semantics; different filters combine with AND semantics. + operationId: listUpcomingEvents + parameters: + - name: category + in: query + description: Filter by category (can specify multiple). If omitted, returns events from all categories. + schema: + type: array + items: + type: string + style: form + explode: true + - $ref: '#/components/parameters/SportFilter' + - $ref: '#/components/parameters/SportsMarketTypeFilter' + - $ref: '#/components/parameters/SportsMarketSubjectFilter' + - $ref: '#/components/parameters/SportsMarketScopeFilter' + - $ref: '#/components/parameters/SportsMarketMetricFilter' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Offset' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/EventsResponse' + examples: + upcomingEvents: + summary: Upcoming events + value: + data: + - id: "4200" + title: "Lakers vs Celtics" + slug: "lakers-vs-celtics-march-10" + description: "NBA game prediction market" + imageUrl: "https://images.ctfassets.net/example.png" + type: "binary" + category: "Sports" + series: null + sportsMarket: + sport: "basketball" + type: "moneyline" + subject: "contest" + scope: + type: "full_contest" + ticker: "NBA260310LAL-BOS" + status: "approved" + resolvedAt: null + createdAt: "2026-03-04T12:00:00.000Z" + effectiveDate: "2026-03-10T19:30:00.000Z" + expiryDate: "2026-03-11T02:00:00.000Z" + liquidity: null + tags: ["NBA", "Basketball"] + subcategory: + id: 10 + slug: "sports_nba" + name: "NBA" + path: ["Sports", "NBA"] + contracts: + - id: "4200-1" + label: "Lakers Win" + abbreviatedName: "LAL" + description: null + prices: + buy: {} + sell: {} + bestBid: null + bestAsk: null + lastTradePrice: null + color: "#552583" + status: "approved" + imageUrl: null + priceHistory: null + createdAt: "2026-03-04T12:00:00.000Z" + expiryDate: "2026-03-11T02:00:00.000Z" + resolutionSide: null + resolvedAt: null + termsAndConditionsUrl: "https://example.com/terms" + ticker: "LAL" + instrumentSymbol: "GEMI-NBA260310LAL-BOS-LAL" + effectiveDate: "2026-03-10T19:30:00.000Z" + marketState: "closed" + sortOrder: 1 + pagination: + limit: 50 + offset: 0 + total: 1 + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/categories: + get: + tags: + - Markets + summary: List event categories + description: Returns available prediction market event categories, optionally filtered by event status. + operationId: getCategories + parameters: + - name: status + in: query + description: Filter categories by event status + schema: + type: array + items: + $ref: '#/components/schemas/MarketStatus' + style: form + explode: true + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + categories: + type: array + items: + type: string + example: ["sports", "politics", "crypto", "entertainment"] + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/volume/{date}: + get: + tags: + - Volume + summary: Get daily prediction market trade volume + description: | + Returns prediction-market trade volume by category for one completed UTC day. This is a public, unauthenticated endpoint. + + `date` must use the `YYYY-MM-DD` UTC calendar-date format. Requests may select one day in the rolling one-year UTC window ending before the current UTC day; the current UTC day is not available. The exact earliest supported date is evaluated for each request. + + Prediction-market volume begins at `2025-12-15`. A pre-launch date, or a post-launch date with any missing source hour, returns `404 NOT_FOUND`. The endpoint never synthesizes zero-volume rows for time before launch. + + All volume values are non-negative decimal strings. Category rows are flat and ordered with each parent before its descendants. Each category row's `volume` includes trades assigned directly to that category and to all descendant categories. + operationId: getPredictionMarketDailyVolume + parameters: + - name: date + in: path + required: true + description: Completed UTC calendar date in `YYYY-MM-DD` format. + schema: + type: string + format: date + responses: + '200': + description: Category volume for the requested UTC day + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PredictionMarketVolumeCategory' + examples: + dailyVolume: + summary: Daily category volume + value: + - categoryPath: ["Sports"] + volume: "200097" + - categoryPath: ["Sports", "Soccer"] + volume: "3952" + '400': + description: Invalid or unsupported date. The message includes the current one-year UTC date bounds. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + invalidDate: + summary: Date must use the required UTC calendar-date format + value: + error: "BAD_REQUEST" + message: "date must use YYYY-MM-DD. Supported one-year UTC date range: <= date < " + '404': + description: No complete volume data is available for the requested date. This includes dates before prediction markets launched and post-launch dates with a missing source hour. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "NOT_FOUND" + message: "Prediction market volume data is not available for the requested date" + '503': + description: The canonical source is invalid or temporarily unavailable. The endpoint does not return a partial result. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "SERVICE_UNAVAILABLE" + message: "Prediction market volume data is temporarily unavailable" + + /v1/prediction-markets/volume/{date}/hourly: + get: + tags: + - Volume + summary: Get hourly prediction market trade volume + description: | + Returns prediction-market trade volume by category and UTC hour for one completed UTC day. This is a public, unauthenticated endpoint. + + `date` must use the `YYYY-MM-DD` UTC calendar-date format. Requests may select one day in the rolling one-year UTC window ending before the current UTC day; the current UTC day is not available. The exact earliest supported date is evaluated for each request. + + Prediction-market volume begins at `2025-12-15`. A pre-launch date, or a post-launch date with any missing source hour, returns `404 NOT_FOUND`. The endpoint never synthesizes zero-volume rows for time before launch or completed zero-volume hours. + + All volume values are non-negative decimal strings. Rows are ordered by UTC hour, then with each category parent before its descendants. Each category row's `volume` includes trades assigned directly to that category and to all descendant categories. + operationId: getPredictionMarketHourlyVolume + parameters: + - name: date + in: path + required: true + description: Completed UTC calendar date in `YYYY-MM-DD` format. + schema: + type: string + format: date + responses: + '200': + description: Hourly category volume for the requested UTC day + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PredictionMarketHourlyVolumeCategory' + examples: + hourlyVolume: + summary: Hourly category volume + value: + - periodStart: "2026-07-20T00:00:00Z" + categoryPath: ["Sports"] + volume: "200097" + - periodStart: "2026-07-20T00:00:00Z" + categoryPath: ["Sports", "Soccer"] + volume: "3952" + '400': + description: Invalid or unsupported date. The message includes the current one-year UTC date bounds. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + invalidDate: + summary: Date must use the required UTC calendar-date format + value: + error: "BAD_REQUEST" + message: "date must use YYYY-MM-DD. Supported one-year UTC date range: <= date < " + '404': + description: No complete volume data is available for the requested date. This includes dates before prediction markets launched and post-launch dates with a missing source hour. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "NOT_FOUND" + message: "Prediction market volume data is not available for the requested date" + '503': + description: The canonical source is invalid or temporarily unavailable. The endpoint does not return a partial result. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "SERVICE_UNAVAILABLE" + message: "Prediction market volume data is temporarily unavailable" + + /v1/prediction-markets/terms: + get: + tags: + - Terms + summary: Get prediction market terms + description: Returns the latest Prediction Markets terms content. This endpoint is public so clients can display the terms before asking an authenticated account to accept them. + operationId: getPredictionMarketsTerms + responses: + '200': + description: Latest Prediction Markets terms + content: + application/json: + schema: + $ref: '#/components/schemas/PredictionMarketsTerms' + examples: + terms: + summary: Latest terms + value: + termsType: "PredictionsMarket" + version: 3 + content: "These are the prediction market terms." + updatedAt: "2026-05-18T17:00:00Z" + '404': + description: No Prediction Markets terms are configured + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "TermsNotFound" + message: "No terms configured for prediction markets" + '500': + $ref: '#/components/responses/InternalError' + + /v1/prediction-markets/terms/status: + get: + tags: + - Terms + summary: Get prediction market terms status + description: Returns whether the authenticated account group has accepted the latest Prediction Markets terms. Requires authentication and OrderStatus permission. + operationId: getPredictionMarketsTermsStatus + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + responses: + '200': + description: Terms acceptance status + content: + application/json: + schema: + $ref: '#/components/schemas/PredictionMarketsTermsStatus' + examples: + accepted: + summary: Latest terms accepted + value: + hasAcceptedLatest: true + acceptedVersion: 3 + latestVersion: 3 + needsAcceptance: + summary: Latest terms not accepted + value: + hasAcceptedLatest: false + acceptedVersion: 2 + latestVersion: 3 + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /v1/prediction-markets/terms/accept: + post: + tags: + - Terms + summary: Accept prediction market terms + description: Accepts the latest configured Prediction Markets terms for the authenticated account group. Requires authentication and NewOrder permission. The actor is recorded from the OAuth client when OAuth is used, otherwise from the API key session. + operationId: acceptPredictionMarketsTerms + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + responses: + '200': + description: Terms accepted + content: + application/json: + schema: + $ref: '#/components/schemas/AcceptPredictionMarketsTermsResponse' + example: + success: true + '401': + $ref: '#/components/responses/Unauthorized' + '404': + description: No Prediction Markets terms are configured + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "TermsNotFound" + message: "No terms configured for prediction markets" + '500': + $ref: '#/components/responses/InternalError' + + /v1/prediction-markets/order: + post: + tags: + - Trading + summary: Place order + description: | + Place a new prediction market order. Supports limit and stop-limit order types. Requires authentication and NewOrder permission. + + Before sending orders, check `GET /v1/prediction-markets/terms/status`. If `hasAcceptedLatest` is `false`, display `GET /v1/prediction-markets/terms` and call `POST /v1/prediction-markets/terms/accept`, then retry the order. + + Validate each order's quantity and price against the instrument-specific `quantityIncrement`, `quantityMinimum`, `priceIncrement`, and `priceMinimum` returned in the contract metadata. Do not assume a fixed quantity or price grid across instruments. + + ### Stop-Limit Orders + A stop-limit order is an order type that allows for order placement when a price reaches a specified level. Stop-limit orders take in both a `price` and a `stopPrice` as parameters. The `stopPrice` is the price that triggers the order to be placed on the continuous live order book at the `price`. For buy orders, the `stopPrice` must be greater than or equal to the last trade price and less than or equal to the `price`; for sell orders, the `stopPrice` must be less than or equal to the last trade price and greater than or equal to the `price`. Both `price` and `stopPrice` must be in the 0-1 range. + operationId: placeOrder + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/OrderRequest' + examples: + buyYes: + summary: Buy YES contract + description: Place a limit order to buy 100 YES contracts at 0.65 + value: + symbol: "GEMI-FEDJAN26-DN25" + orderType: "limit" + side: "buy" + quantity: "100" + price: "0.65" + outcome: "yes" + timeInForce: "good-til-cancel" + sellNo: + summary: Sell NO contract + description: Place a limit order to sell 50 NO contracts at 0.35 + value: + symbol: "GEMI-FEDJAN26-DN25" + orderType: "limit" + side: "sell" + quantity: "50" + price: "0.35" + outcome: "no" + timeInForce: "good-til-cancel" + makerOnly: + summary: Maker-only order (post-only) + description: Place a maker-only order that will be cancelled if it would match immediately. Useful for ensuring you provide liquidity and qualify for maker rebates. + value: + symbol: "GEMI-FEDJAN26-DN25" + orderType: "limit" + side: "buy" + quantity: "100" + price: "0.55" + outcome: "yes" + timeInForce: "good-til-cancel" + makerOrCancel: true + buyYesStopLimit: + summary: Buy YES stop-limit + description: Place a stop-limit order to buy 100 YES contracts at 0.70 once the market reaches the stop trigger of 0.65. + value: + symbol: "GEMI-FEDJAN26-DN25" + orderType: "stop-limit" + side: "buy" + quantity: "100" + price: "0.70" + stopPrice: "0.65" + outcome: "yes" + timeInForce: "good-til-cancel" + sellNoStopLimit: + summary: Sell NO stop-limit + description: Place a stop-limit order to sell 50 NO contracts at 0.40 once the market falls to the stop trigger of 0.45. + value: + symbol: "GEMI-FEDJAN26-DN25" + orderType: "stop-limit" + side: "sell" + quantity: "50" + price: "0.40" + stopPrice: "0.45" + outcome: "no" + timeInForce: "good-til-cancel" + responses: + '201': + description: Order created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/OrderResponse' + examples: + orderPlaced: + summary: Order successfully placed + value: + orderId: 12345678901 + status: "open" + symbol: "GEMI-FEDJAN26-DN25" + side: "buy" + outcome: "yes" + orderType: "limit" + quantity: "100" + filledQuantity: "0" + remainingQuantity: "100" + price: "0.65" + avgExecutionPrice: null + createdAt: "2025-12-15T10:30:00.000Z" + updatedAt: "2025-12-15T10:30:00.000Z" + cancelledAt: null + contractMetadata: + contractId: "contract_123" + contractName: "FEDJAN26-DN25" + contractTicker: "FEDJAN26-DN25" + eventTicker: "FEDJAN26" + eventName: "Will Fed Funds Rate drop at least 0.25% at January 2026 meeting?" + category: "economics" + contractStatus: "active" + imageUrl: "https://example.com/fed.png" + expiryDate: "2026-01-31T23:59:59.000Z" + resolvedAt: null + description: "Resolves YES if Federal Reserve lowers the target rate by 0.25% or more at the January 2026 FOMC meeting" + stopLimitOrderPlaced: + summary: Stop-limit order successfully placed + value: + orderId: 12345678902 + status: "open" + symbol: "GEMI-FEDJAN26-DN25" + side: "buy" + outcome: "yes" + orderType: "stop-limit" + quantity: "100" + filledQuantity: "0" + remainingQuantity: "100" + price: "0.70" + stopPrice: "0.65" + avgExecutionPrice: null + createdAt: "2025-12-15T10:30:00.000Z" + updatedAt: "2025-12-15T10:30:00.000Z" + cancelledAt: null + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '422': + description: Order rejected (e.g., insufficient funds) + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/order/batch: + post: + tags: + - Trading + summary: Place a batch of orders + description: | + Place between 1 and 20 prediction market orders in one authenticated request. The complete payload is signed once using the standard private REST authentication headers. Each entry accepts the same fields as `POST /v1/prediction-markets/order`. + + The operation is synchronous and non-atomic. Gemini validates the entire batch before submitting any orders. If the batch or any entry fails up-front validation, the request fails and no orders are submitted. After validation succeeds, orders are submitted sequentially and each result is returned in request order. An exchange rejection for one order does not stop later orders from being submitted; it appears as an `error` and `message` for that entry in the `200` response. + operationId: placeOrderBatch + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOrderBatchRequest' + examples: + twoOrders: + summary: Place two orders + value: + orders: + - symbol: "GEMI-FEDJAN26-DN25" + orderType: "limit" + side: "buy" + quantity: "100" + price: "0.65" + outcome: "yes" + timeInForce: "good-til-cancel" + - symbol: "GEMI-FEDJAN26-DN25" + orderType: "limit" + side: "sell" + quantity: "50" + price: "0.35" + outcome: "no" + timeInForce: "good-til-cancel" + responses: + '200': + description: Batch processed. Results are returned in request order and may contain both successful orders and per-entry errors. + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOrderBatchResponse' + examples: + partialSuccess: + summary: One order accepted and one order rejected + value: + results: + - order: + orderId: 12345678901 + status: "open" + symbol: "GEMI-FEDJAN26-DN25" + side: "buy" + outcome: "yes" + orderType: "limit" + timeInForce: "good-til-cancel" + quantity: "100" + filledQuantity: "0" + remainingQuantity: "100" + price: "0.65" + createdAt: "2025-12-15T10:30:00.000Z" + updatedAt: "2025-12-15T10:30:00.000Z" + - error: "InsufficientFunds" + message: "Insufficient funds" + '400': + description: Invalid payload, empty batch, more than 20 entries, or an invalid order. No orders are submitted. + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/AuthErrorResponse' + - $ref: '#/components/schemas/PredictionMarketsError' + '401': + description: Authentication is missing or invalid. + content: + application/json: + schema: + $ref: '#/components/schemas/AuthErrorResponse' + '403': + description: The account is not permitted to place orders or has not accepted the current Prediction Markets terms. No orders are submitted. + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/AuthErrorResponse' + - $ref: '#/components/schemas/AccountGroupBlockedError' + - $ref: '#/components/schemas/TermsNotAcceptedError' + - $ref: '#/components/schemas/RestrictedSellOnlyError' + '409': + description: The request nonce conflicts with a previously submitted request. + content: + application/json: + schema: + $ref: '#/components/schemas/AuthErrorResponse' + '422': + description: An order failed an up-front risk check. No orders are submitted. + content: + application/json: + schema: + $ref: '#/components/schemas/PredictionMarketsError' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/PredictionMarketsError' + '503': + description: Prediction markets or batch orders are temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/PredictionMarketsError' + + /v1/prediction-markets/order/cancel: + post: + tags: + - Trading + summary: Cancel order + description: Cancel an existing prediction market order. Requires authentication and CancelOrder permission. + operationId: cancelOrder + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - orderId + properties: + orderId: + type: integer + format: int64 + description: The order ID to cancel + example: 12345678 + responses: + '200': + description: Order cancelled successfully + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: "ok" + message: + type: string + example: "Order 12345678 cancelled successfully" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + description: Order not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '422': + description: Order cannot be cancelled (e.g., already filled) + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/order/batch/cancel: + post: + tags: + - Trading + summary: Cancel a batch of orders + description: | + Cancel between 1 and 20 prediction market orders in one authenticated request. The complete payload is signed once using the standard private REST authentication headers. Each order ID may be a JSON integer or a quoted numeric string. + + The operation is synchronous and non-atomic. Gemini validates all order IDs before attempting any cancellation. If the batch is empty, contains more than 20 entries, or contains an invalid ID, the request fails and no orders are cancelled. After validation succeeds, cancellations are attempted sequentially and each result is returned in request order. A rejection for one cancellation does not stop later cancellations from being attempted; it appears as an `error` and `message` for that entry in the `200` response. + operationId: cancelOrderBatch + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CancelOrderBatchRequest' + examples: + twoOrders: + summary: Cancel two orders + value: + orderIds: + - 12345678 + - "12345679" + responses: + '200': + description: Batch processed. Results are returned in request order and may contain both successful cancellations and per-entry errors. + content: + application/json: + schema: + $ref: '#/components/schemas/CancelOrderBatchResponse' + examples: + partialSuccess: + summary: One order cancelled and one order not found + value: + results: + - orderId: 12345678 + result: "ok" + - orderId: 12345679 + error: "OrderNotFound" + message: "Order 12345679 not found" + '400': + description: Invalid payload, empty batch, more than 20 entries, or an invalid order ID. No orders are cancelled. + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/AuthErrorResponse' + - $ref: '#/components/schemas/PredictionMarketsError' + '401': + description: Authentication is missing or invalid. + content: + application/json: + schema: + $ref: '#/components/schemas/AuthErrorResponse' + '403': + description: The account is not permitted to cancel orders. + content: + application/json: + schema: + $ref: '#/components/schemas/AuthErrorResponse' + '409': + description: The request nonce conflicts with a previously submitted request. + content: + application/json: + schema: + $ref: '#/components/schemas/AuthErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/PredictionMarketsError' + '503': + description: Prediction markets or batch orders are temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/PredictionMarketsError' + + # /v1/prediction-markets/order/quote: + # get: + # tags: + # - Trading + # summary: Get price quote + # description: | + # Get a price quote for buying/selling contracts. Provide either `shares` OR `totalSpend`, not both. + # Requires authentication. + # operationId: getQuote + # security: + # - apiKey: [] + # parameters: + # - name: symbol + # in: query + # required: true + # description: The contract instrument symbol + # schema: + # type: string + # example: "GEMI-FEDJAN26-DN25" + # - name: shares + # in: query + # description: Number of shares to quote (mutually exclusive with totalSpend) + # schema: + # type: string + # example: "100" + # - name: totalSpend + # in: query + # description: Total amount to spend in USD (mutually exclusive with shares) + # schema: + # type: string + # example: "50.00" + # responses: + # '200': + # description: Successful quote + # content: + # application/json: + # schema: + # oneOf: + # - $ref: '#/components/schemas/QuoteByQuantityResponse' + # - $ref: '#/components/schemas/QuoteBySpendResponse' + # '400': + # $ref: '#/components/responses/BadRequest' + # '401': + # $ref: '#/components/responses/Unauthorized' + # '404': + # description: Contract not found + # content: + # application/json: + # schema: + # $ref: '#/components/schemas/Error' + # '500': + # $ref: '#/components/responses/InternalError' + # '503': + # $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/orders/active: + post: + tags: + - Positions + summary: Get active orders + description: Returns a list of currently open (active) orders. Requires authentication. + operationId: getActiveOrders + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + symbol: + type: string + description: Filter by contract instrument symbol + example: "GEMI-FEDJAN26-DN25" + limit: + type: integer + description: Maximum number of results to return (default 50, max 100) + default: 50 + maximum: 100 + offset: + type: integer + description: Number of results to skip for pagination + default: 0 + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/OrdersResponse' + examples: + activeOrders: + summary: List of active orders + value: + orders: + - orderId: 12345678901 + status: "open" + symbol: "GEMI-FEDJAN26-DN25" + side: "buy" + outcome: "yes" + orderType: "limit" + quantity: "100" + filledQuantity: "25" + remainingQuantity: "75" + price: "0.65" + avgExecutionPrice: "0.64" + createdAt: "2025-12-15T10:30:00.000Z" + updatedAt: "2025-12-15T11:00:00.000Z" + cancelledAt: null + contractMetadata: + contractId: "contract_123" + contractName: "FEDJAN26-DN25" + contractTicker: "FEDJAN26-DN25" + eventTicker: "FEDJAN26" + eventName: "Will Fed Funds Rate drop at least 0.25% at January 2026 meeting?" + category: "economics" + contractStatus: "active" + imageUrl: "https://example.com/fed.png" + expiryDate: "2026-01-31T23:59:59.000Z" + resolvedAt: null + description: "Resolves YES if Federal Reserve lowers the target rate by 0.25% or more at the January 2026 FOMC meeting" + - orderId: 12345678902 + status: "open" + symbol: "GEMI-FEDJAN26-DN25" + side: "sell" + outcome: "yes" + orderType: "limit" + quantity: "50" + filledQuantity: "0" + remainingQuantity: "50" + price: "0.65" + avgExecutionPrice: null + createdAt: "2025-12-15T12:00:00.000Z" + updatedAt: "2025-12-15T12:00:00.000Z" + cancelledAt: null + contractMetadata: + contractId: "contract_123" + contractName: "FEDJAN26-DN25" + contractTicker: "FEDJAN26-DN25" + eventTicker: "FEDJAN26" + eventName: "Will Fed Funds Rate drop at least 0.25% at January 2026 meeting?" + category: "economics" + contractStatus: "active" + imageUrl: "https://example.com/fed.png" + expiryDate: "2026-01-31T23:59:59.000Z" + resolvedAt: null + description: "Resolves YES if Federal Reserve lowers the target rate by 0.25% or more at the January 2026 FOMC meeting" + pagination: + limit: 50 + offset: 0 + count: 2 + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/orders/history: + post: + tags: + - Positions + summary: Get order history + description: >- + Returns historical orders (filled or cancelled) for the authenticated user. Use `status: filled` with `from` and `to` to retrieve fully filled orders in a bounded time window. The range is `[from, to)`: `from` is inclusive and `to` is exclusive. A time-bounded response contains at most `limit` results and ignores `offset`; split high-volume periods into non-overlapping ranges. Use `/orders/active` for open orders. + operationId: getOrderHistory + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + status: + type: string + description: Filter by order status + enum: [filled, cancelled] + symbol: + type: string + description: Filter by contract instrument symbol + example: "GEMI-FEDJAN26-DN25" + limit: + type: integer + description: Maximum number of results to return. Defaults to 50 and is capped at 1000. + default: 50 + minimum: 1 + maximum: 1000 + offset: + type: integer + description: Number of results to skip for pagination. Offset is ignored when `from` or `to` is supplied. + default: 0 + minimum: 0 + maximum: 10000 + from: + type: integer + format: int64 + description: Inclusive start of the order-closed time range, expressed as Unix epoch milliseconds. Use with `to` for a UTC daily window. + example: 1775001600000 + to: + type: integer + format: int64 + description: Exclusive end of the order-closed time range, expressed as Unix epoch milliseconds. `from` must not be later than `to`. + example: 1775088000000 + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/OrdersResponse' + '400': + description: Invalid status parameter or date range + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/positions: + post: + tags: + - Positions + summary: Get positions + description: | + Returns current filled positions for the authenticated user. All query parameters are optional; omitting them preserves the legacy unpaginated, unsorted behavior. + operationId: getPositions + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + parameters: + - name: eventTicker + in: query + required: false + description: Filter positions to a single event ticker (e.g. `FEDJAN26`). Positions on sub-events whose `parentEventTicker` matches the value may also be included. + schema: + type: string + - name: limit + in: query + required: false + description: Maximum number of positions to return. Clamped to `[1, 1000]` when supplied. Omit for legacy unpaginated behavior. + schema: + type: integer + minimum: 1 + maximum: 1000 + - name: offset + in: query + required: false + description: Number of positions to skip for pagination. Floor-clamped to `0` when supplied. Ignored when `limit` is omitted (the response is unpaginated). + schema: + type: integer + minimum: 0 + - name: sort + in: query + required: false + description: | + Sort order. Accepts `positionValue`, `unrealizedPnl`, or `expiryDate` (case-insensitive), optionally prefixed with `+` (ascending) or `-` (descending). A bare field name uses each field's default direction: `positionValue` and `unrealizedPnl` default to descending; `expiryDate` defaults to ascending (soonest-first). `unrealizedPnl` and `expiryDate` sort NULLS LAST so positions without the sort key sink to the bottom regardless of direction. `instrumentId` ascending is the final tiebreaker for stable pagination across quote ticks. A malformed `sort` value silently falls back to `-positionValue` — no `400` is returned. + schema: + type: string + enum: + - positionValue + - '+positionValue' + - '-positionValue' + - unrealizedPnl + - '+unrealizedPnl' + - '-unrealizedPnl' + - expiryDate + - '+expiryDate' + - '-expiryDate' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/PositionsResponse' + examples: + positions: + summary: User positions + value: + positions: + - symbol: "GEMI-FEDJAN26-DN25" + instrumentId: 1001 + totalQuantity: "125" + quantityOnHold: "10" + avgPrice: "0.63" + outcome: "yes" + contractMetadata: + contractId: "contract_123" + contractName: "FEDJAN26-DN25" + contractTicker: "FEDJAN26-DN25" + eventTicker: "FEDJAN26" + eventName: "Will Fed Funds Rate drop at least 0.25% at January 2026 meeting?" + category: "economics" + contractStatus: "active" + imageUrl: "https://example.com/fed.png" + eventImageUrl: "https://example.com/fed-event.png" + eventType: "binary" + expiryDate: "2026-01-31T23:59:59.000Z" + resolvedAt: null + resolutionSide: null + description: "Resolves YES if Federal Reserve lowers the target rate by 0.25% or more at the January 2026 FOMC meeting" + sortOrder: null + parentEventTicker: null + template: "binary" + color: null + startTime: null + prices: + buy: + yes: "0.63" + no: "0.37" + sell: + yes: "0.61" + no: "0.35" + bestBid: "0.61" + bestAsk: "0.63" + lastTradePrice: "0.62" + resolutionSide: null + isAboveAutoStartThreshold: false + isLive: true + realizedPl: "0" + marketValue: "78.75" + unrealizedPnl: "0" + unrealizedPct: 0 + - symbol: "GEMI-FEDJAN26-DN25" + instrumentId: 1001 + totalQuantity: "200" + quantityOnHold: "0" + avgPrice: "0.36" + outcome: "no" + contractMetadata: + contractId: "contract_123" + contractName: "FEDJAN26-DN25" + contractTicker: "FEDJAN26-DN25" + eventTicker: "FEDJAN26" + eventName: "Will Fed Funds Rate drop at least 0.25% at January 2026 meeting?" + category: "economics" + contractStatus: "active" + imageUrl: "https://example.com/fed.png" + eventImageUrl: "https://example.com/fed-event.png" + eventType: "binary" + expiryDate: "2026-01-31T23:59:59.000Z" + resolvedAt: null + resolutionSide: null + description: "Resolves YES if Federal Reserve lowers the target rate by 0.25% or more at the January 2026 FOMC meeting" + sortOrder: null + parentEventTicker: null + template: "binary" + color: null + startTime: null + prices: + buy: + yes: "0.37" + no: "0.63" + sell: + yes: "0.35" + no: "0.61" + bestBid: "0.35" + bestAsk: "0.37" + lastTradePrice: "0.36" + resolutionSide: null + isAboveAutoStartThreshold: false + isLive: true + realizedPl: "0" + marketValue: "72.00" + unrealizedPnl: "0" + unrealizedPct: 0 + total: 2 + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/positions/settled: + post: + tags: + - Positions + summary: Get settled positions + description: | + Returns historically settled positions for the authenticated user. Each entry represents a position in a contract that has resolved. + - `payout` — the amount received from settlement + - `resolutionSide` — indicates which outcome (`yes` or `no`) won. + + This endpoint differs from [Get positions](#operation/getPositions) in that it returns closed positions from settled contracts rather than current open positions. + operationId: getSettledPositions + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + parameters: + - name: eventTicker + in: query + description: Optional event ticker to filter settled positions to a single event (e.g. `FEDJAN26`). If omitted, all settled positions for the account are returned. + required: false + schema: + type: string + - name: limit + in: query + required: false + description: Maximum number of settled positions to return. + schema: + type: integer + default: 1000 + minimum: 1 + maximum: 1000 + - name: offset + in: query + required: false + description: Number of settled positions to skip for pagination. + schema: + type: integer + default: 0 + minimum: 0 + - name: sort + in: query + required: false + description: | + Sort order. Accepts `date` or `payout`, optionally prefixed with `+` (ascending) or `-` (descending). A bare field name defaults to descending. `date` ascending is rejected and silently falls back to the default order — settled positions are conceptually ordered most-recent-first. A malformed `sort` value also falls back silently; no `400` is returned. + schema: + type: string + enum: + - date + - '-date' + - payout + - '+payout' + - '-payout' + example: "-payout" + - name: search + in: query + required: false + description: | + Case-insensitive substring filter. Matches against the event name, contract name, event ticker, or any ancestor category name in the contract's category subtree (up to four levels). Whitespace is trimmed; inputs under 3 characters are dropped (GIN trigram lookup floor); inputs over 64 characters are truncated. + schema: + type: string + - name: category + in: query + required: false + description: | + Filter to settled positions whose contract's event belongs to the named category (or any of its descendants in the category tree). Whitespace is trimmed; empty values are ignored. + schema: + type: string + example: "sports" + - name: withCashOuts + in: query + required: false + description: | + Opt-in flag. When `true`, the response carries new sibling fields (`cashOuts`, `totalCashOutProceeds`, `totalCashOutCostBasis`, `totalCashOutNetProfit`) populated with the qualifying cash-outs in the same account-scoped time window as the returned page's settled positions. When `false` (default) the response shape is byte-identical to the pre-`withCashOuts` contract: the `positions[]` element schema is unchanged regardless of the flag. + schema: + type: boolean + default: false + example: true + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/SettledPositionsResponse' + examples: + settledPositions: + summary: Settled positions with one winning and one losing position + value: + positions: + - accountId: 12345 + instrumentId: 1001 + instrumentSymbol: "GEMI-FEDJAN26-DN25" + position: "125" + positionQuantity: "125" + outcome: "yes" + payout: "125.00" + resolutionSide: "yes" + settledAt: "2026-01-31T23:59:59.000Z" + contractMetadata: + contractId: "contract_123" + contractName: "FEDJAN26-DN25" + contractTicker: "FEDJAN26-DN25" + eventTicker: "FEDJAN26" + eventName: "Will Fed Funds Rate drop at least 0.25% at January 2026 meeting?" + category: "economics" + contractStatus: "resolved" + imageUrl: "https://example.com/fed.png" + eventImageUrl: "https://example.com/fed-event.png" + eventType: "binary" + expiryDate: "2026-01-31T23:59:59.000Z" + resolvedAt: "2026-01-31T23:59:59.000Z" + resolutionSide: "yes" + description: "Resolves YES if Federal Reserve lowers the target rate by 0.25% or more at the January 2026 FOMC meeting" + sortOrder: null + parentEventTicker: null + template: "binary" + color: null + startTime: null + costBasis: "78.75" + realizedPnl: "0" + netProfit: "46.25" + - accountId: 12345 + instrumentId: 1002 + instrumentSymbol: "GEMI-FEDJAN26-NOCUT" + position: "-200" + positionQuantity: "200" + outcome: "no" + payout: "0" + resolutionSide: "yes" + settledAt: "2026-01-31T23:59:59.000Z" + contractMetadata: + contractId: "contract_124" + contractName: "FEDJAN26-NOCUT" + contractTicker: "FEDJAN26-NOCUT" + eventTicker: "FEDJAN26" + eventName: "Will Fed Funds Rate drop at least 0.25% at January 2026 meeting?" + category: "economics" + contractStatus: "resolved" + imageUrl: "https://example.com/fed.png" + eventImageUrl: "https://example.com/fed-event.png" + eventType: "binary" + expiryDate: "2026-01-31T23:59:59.000Z" + resolvedAt: "2026-01-31T23:59:59.000Z" + resolutionSide: "yes" + description: "Resolves YES if Federal Reserve lowers the target rate by 0.25% or more at the January 2026 FOMC meeting" + sortOrder: null + parentEventTicker: null + template: "binary" + color: null + startTime: null + costBasis: "72.00" + realizedPnl: "0" + netProfit: "-72.00" + total: 2 + settledPositionsWithCashOuts: + summary: Same response with `withCashOuts=true` + value: + positions: + - accountId: 12345 + instrumentId: 1001 + instrumentSymbol: "GEMI-FEDJAN26-DN25" + position: "125" + positionQuantity: "125" + outcome: "yes" + payout: "125.00" + resolutionSide: "yes" + settledAt: "2026-01-31T23:59:59.000Z" + contractMetadata: + contractId: "contract_123" + contractName: "FEDJAN26-DN25" + contractTicker: "FEDJAN26-DN25" + eventTicker: "FEDJAN26" + eventName: "Will Fed Funds Rate drop at least 0.25% at January 2026 meeting?" + category: "economics" + contractStatus: "resolved" + imageUrl: "https://example.com/fed.png" + eventImageUrl: "https://example.com/fed-event.png" + eventType: "binary" + expiryDate: "2026-01-31T23:59:59.000Z" + resolvedAt: "2026-01-31T23:59:59.000Z" + resolutionSide: "yes" + description: "Resolves YES if Federal Reserve lowers the target rate by 0.25% or more at the January 2026 FOMC meeting" + sortOrder: null + parentEventTicker: null + template: "binary" + color: null + startTime: null + costBasis: "78.75" + realizedPnl: "0" + netProfit: "46.25" + total: 1 + cashOuts: + - accountId: 12345 + instrumentId: 1003 + instrumentSymbol: "GEMI-FEDJAN26-DN25" + timestamp: "2026-01-28T10:15:00.000Z" + filledQuantity: "10" + side: "sell" + proceeds: "6.50" + costBasis: "6.30" + netProfit: "0.20" + contractMetadata: + contractId: "contract_123" + contractName: "FEDJAN26-DN25" + contractTicker: "FEDJAN26-DN25" + eventTicker: "FEDJAN26" + eventName: "Will Fed Funds Rate drop at least 0.25% at January 2026 meeting?" + category: "economics" + contractStatus: "resolved" + imageUrl: "https://example.com/fed.png" + eventImageUrl: "https://example.com/fed-event.png" + eventType: "binary" + expiryDate: "2026-01-31T23:59:59.000Z" + resolvedAt: "2026-01-31T23:59:59.000Z" + resolutionSide: "yes" + description: "Resolves YES if Federal Reserve lowers the target rate by 0.25% or more at the January 2026 FOMC meeting" + sortOrder: null + parentEventTicker: null + template: "binary" + color: null + startTime: null + totalCashOutProceeds: "6.50" + totalCashOutCostBasis: "6.30" + totalCashOutNetProfit: "0.20" + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/metrics/volume: + post: + tags: + - Positions + summary: Get volume metrics + description: | + Returns per-contract share volume metrics for an event, including the authenticated user's taker and maker volumes. + + All volumes are in shares (number of contracts traded), not dollar amounts. + + - `totalQty` — Total taker volume across all participants for this contract + - `userAggressorQty` — The authenticated user's taker (aggressor) volume + - `userRestingQty` — The authenticated user's maker (resting) volume, counted when another order fills against the user's resting limit order + + An optional time range can be specified to filter trades within a specific window. + operationId: getVolumeMetrics + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - eventTicker + properties: + eventTicker: + type: string + description: The event ticker symbol + example: "FED260318" + startTime: + type: integer + format: int64 + description: Start of time range filter (epoch milliseconds). If omitted, defaults to the earliest contract creation time. + endTime: + type: integer + format: int64 + description: End of time range filter (epoch milliseconds). If omitted, includes all trades up to now. + examples: + allTime: + summary: All-time volume for an event + value: + eventTicker: "FED260318" + timeRanged: + summary: Volume within a specific time range + value: + eventTicker: "FED260318" + startTime: 1772412364000 + endTime: 1772671564000 + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/VolumeMetricsResponse' + examples: + volumeMetrics: + summary: Volume metrics for a multi-contract event + value: + eventTicker: "FED260318" + contracts: + - symbol: "GEMI-FED260318-CUT25" + totalQty: "94625" + userAggressorQty: "1" + userRestingQty: "0" + - symbol: "GEMI-FED260318-CUTGT25" + totalQty: "68666" + userAggressorQty: "0" + userRestingQty: "0" + - symbol: "GEMI-FED260318-HIKE" + totalQty: "15397" + userAggressorQty: "0" + userRestingQty: "0" + - symbol: "GEMI-FED260318-MAINTAIN" + totalQty: "20400" + userAggressorQty: "5" + userRestingQty: "0" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/combos: + get: + tags: + - Combos + summary: List combo contracts + description: Returns a paginated list of combo contracts. Each combo includes its full leg breakdown and per-leg resolution status. When `status` is omitted, the endpoint returns only `Active` combos. This Combo Prediction Markets endpoint is not currently enabled in production. + operationId: listCombos + parameters: + - name: status + in: query + required: false + description: Filter by combo contract status (for example, `Active`, `Settled`, or `Voided`). Defaults to `Active` when omitted. + schema: + type: string + - name: contractId + in: query + required: false + description: Filter to combos that contain a specific underlying contract ID as a leg + schema: + type: integer + format: int64 + - name: instrumentRegistered + in: query + required: false + description: Filter by whether the combo has been registered with an instrument symbol + schema: + type: boolean + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Offset' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/ListCombosResponse' + examples: + activeCombos: + summary: List of active combo contracts + value: + combos: + - contract: + contractId: "456" + contractName: "BTC EOY26 > $120k AND ETH EOY26 > $4k" + contractTicker: "GEMI-CMB-0526-A7F3B2C1D4E5" + eventTicker: "GEMI-CMB-0526-A7F3B2C1D4E5" + eventName: "BTC EOY26 > $120k AND ETH EOY26 > $4k" + category: "Combo" + contractStatus: "Active" + eventType: "binary" + expiryDate: "2026-12-31T23:59:59Z" + resolvedAt: null + resolutionSide: null + parentEventTicker: null + startTime: null + legs: + - comboId: 456 + legIndex: 0 + contractId: "101" + requiredOutcome: "Yes" + legOutcome: null + resolvedAt: null + contract: + contractId: "101" + contractName: "BTC above $120,000 at year-end 2026" + contractTicker: "GEMI-BTC-EOY26-HI120000" + eventTicker: "GEMI-BTC-EOY26" + eventName: "Bitcoin Year-End 2026" + category: "Crypto" + contractStatus: "Active" + eventType: "binary" + expiryDate: "2026-12-31T23:59:59Z" + resolvedAt: null + resolutionSide: null + parentEventTicker: null + startTime: null + - comboId: 456 + legIndex: 1 + contractId: "202" + requiredOutcome: "Yes" + legOutcome: null + resolvedAt: null + contract: + contractId: "202" + contractName: "ETH above $4,000 at year-end 2026" + contractTicker: "GEMI-ETH-EOY26-HI4000" + eventTicker: "GEMI-ETH-EOY26" + eventName: "Ethereum Year-End 2026" + category: "Crypto" + contractStatus: "Active" + eventType: "binary" + expiryDate: "2026-12-31T23:59:59Z" + resolvedAt: null + resolutionSide: null + parentEventTicker: null + startTime: null + pagination: + limit: 50 + offset: 0 + total: 1 + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + post: + tags: + - Combos + summary: Create or retrieve a canonical combo + description: | + Creates a combo from two to six underlying contract legs for the authenticated account. The service canonicalizes the complete leg set, so submitting the same legs again returns the existing combo regardless of leg order. The account is derived from the authenticated API key; do not include an account ID in the request. This Combo Prediction Markets endpoint is not currently enabled in production. + + Requires signed private REST authentication, the `PredictionsNewOrder` permission, and an unrestricted trading account. A new canonical combo returns `201 Created` with `alreadyExisted: false`; an existing canonical combo returns `200 OK` with `alreadyExisted: true`. + operationId: createCombo + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateComboRequest' + examples: + twoLegCombo: + summary: Create a two-leg combo + value: + legs: + - contractId: "101" + requiredOutcome: "Yes" + - contractId: "202" + requiredOutcome: "No" + responses: + '200': + description: The canonical combo already exists. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateComboResponse' + examples: + existingCombo: + summary: Existing canonical combo + value: + combo: + id: 456 + canonicalLegKey: "101:Yes|202:No" + legCount: 2 + displayName: "BTC EOY26 > $120k AND ETH EOY26 <= $4k" + status: "Active" + instrumentId: 98765 + instrumentSymbol: "GEMI-CMB-0526-A7F3B2C1D4E5" + instrumentRegistered: true + latestExpiryDate: "2026-12-31T23:59:59.000Z" + createdAt: "2026-05-01T12:00:00.000Z" + updatedAt: "2026-05-01T12:00:00.000Z" + legs: + - comboId: 456 + legIndex: 0 + contractId: "101" + requiredOutcome: "Yes" + - comboId: 456 + legIndex: 1 + contractId: "202" + requiredOutcome: "No" + alreadyExisted: true + '201': + description: A new canonical combo was created. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateComboResponse' + examples: + createdCombo: + summary: New canonical combo + value: + combo: + id: 456 + canonicalLegKey: "101:Yes|202:No" + legCount: 2 + displayName: "BTC EOY26 > $120k AND ETH EOY26 <= $4k" + status: "Active" + instrumentId: 98765 + instrumentSymbol: "GEMI-CMB-0526-A7F3B2C1D4E5" + instrumentRegistered: true + latestExpiryDate: "2026-12-31T23:59:59.000Z" + createdAt: "2026-05-01T12:00:00.000Z" + updatedAt: "2026-05-01T12:00:00.000Z" + legs: + - comboId: 456 + legIndex: 0 + contractId: "101" + requiredOutcome: "Yes" + - comboId: 456 + legIndex: 1 + contractId: "202" + requiredOutcome: "No" + alreadyExisted: false + '400': + description: The request body is malformed or fails combo validation. + content: + application/json: + schema: + $ref: '#/components/schemas/ComboWriteError' + example: + error: "InvalidInput" + code: "COMBO_VALIDATION_ERROR" + message: "a combo needs 2-6 legs" + '401': + description: Signed private REST authentication is missing or invalid. + content: + application/json: + schema: + $ref: '#/components/schemas/AuthErrorResponse' + '403': + description: The API key lacks `PredictionsNewOrder`, or the authenticated trading account is restricted. + content: + application/json: + schema: + $ref: '#/components/schemas/AuthErrorResponse' + '404': + description: Combos are unavailable, or an underlying contract in the request cannot be found. + content: + application/json: + schema: + $ref: '#/components/schemas/ComboWriteError' + examples: + comboUnavailable: + summary: Combos unavailable + value: + error: "NOT_FOUND" + message: "Not Found" + legNotFound: + summary: Underlying contract not found + value: + error: "NOT_FOUND" + code: "COMBO_LEG_NOT_FOUND" + message: "One or more contracts in this combo could not be found. Update your selection and try again." + '500': + description: An unexpected error occurred while creating the combo. + content: + application/json: + schema: + $ref: '#/components/schemas/ComboWriteError' + example: + error: "InternalError" + message: "An unexpected error occurred" + + /v1/prediction-markets/combos/{instrumentSymbol}: + get: + tags: + - Combos + summary: Get combo by instrument symbol + description: Returns the full specification of a single combo contract identified by its instrument symbol, including leg breakdown and per-leg resolution status. This Combo Prediction Markets endpoint is not currently enabled in production. + operationId: getComboByInstrumentSymbol + parameters: + - name: instrumentSymbol + in: path + required: true + description: The combo contract's instrument symbol (e.g. `GEMI-CMB-0526-A7F3B2C1D4E5`) + schema: + type: string + example: "GEMI-CMB-0526-A7F3B2C1D4E5" + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/ComboResponse' + examples: + comboDetail: + summary: Combo contract detail + value: + contract: + contractId: "456" + contractName: "BTC EOY26 > $120k AND ETH EOY26 > $4k" + contractTicker: "GEMI-CMB-0526-A7F3B2C1D4E5" + eventTicker: "GEMI-CMB-0526-A7F3B2C1D4E5" + eventName: "BTC EOY26 > $120k AND ETH EOY26 > $4k" + category: "Combo" + contractStatus: "Active" + eventType: "binary" + expiryDate: "2026-12-31T23:59:59Z" + resolvedAt: null + resolutionSide: null + parentEventTicker: null + startTime: null + legs: + - comboId: 456 + legIndex: 0 + contractId: "101" + requiredOutcome: "Yes" + legOutcome: null + resolvedAt: null + contract: + contractId: "101" + contractName: "BTC above $120,000 at year-end 2026" + contractTicker: "GEMI-BTC-EOY26-HI120000" + eventTicker: "GEMI-BTC-EOY26" + eventName: "Bitcoin Year-End 2026" + category: "Crypto" + contractStatus: "Active" + eventType: "binary" + expiryDate: "2026-12-31T23:59:59Z" + resolvedAt: null + resolutionSide: null + parentEventTicker: null + startTime: null + - comboId: 456 + legIndex: 1 + contractId: "202" + requiredOutcome: "Yes" + legOutcome: null + resolvedAt: null + contract: + contractId: "202" + contractName: "ETH above $4,000 at year-end 2026" + contractTicker: "GEMI-ETH-EOY26-HI4000" + eventTicker: "GEMI-ETH-EOY26" + eventName: "Ethereum Year-End 2026" + category: "Crypto" + contractStatus: "Active" + eventType: "binary" + expiryDate: "2026-12-31T23:59:59Z" + resolvedAt: null + resolutionSide: null + parentEventTicker: null + startTime: null + '404': + description: Combo not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "NOT_FOUND" + message: "Combo not found" + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + + /v1/prediction-markets/maker-rebate/rates: + get: + tags: + - Rewards + summary: Get maker-rebate rate schedule + description: | + Returns the current Maker Rebate rate rules. Public endpoint; no authentication required. + + Each rule defines a `rebate_multiplier_bps` (basis points of the maker fee that is rebated) and an `effective_from` timestamp. An optional `category` scopes the rule to a single market category (omitted rules apply to all categories). An optional `effective_to` marks a rule as superseded. + + Returns `503` with `error: "Maker rebate program is not currently available"` when the program is disabled. + operationId: getMakerRebateRates + parameters: + - name: category + in: query + description: Filter to rules that apply to this category (e.g. `Crypto`, `Sports`). When omitted, returns all rules. + required: false + schema: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/MakerRebateRatesResponse' + examples: + allCategories: + summary: Full rate schedule + value: + rate_rules: + - id: 12 + rebate_multiplier_bps: 5000 + effective_from: "2026-03-19T00:00:00Z" + category: "Crypto" + - id: 13 + rebate_multiplier_bps: 2500 + effective_from: "2026-03-19T00:00:00Z" + category: "Sports" + effective_to: "2026-04-19T00:00:00Z" + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "An unexpected error occurred" + '503': + description: Maker rebate program is not currently available + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "Maker rebate program is not currently available" + + /v1/prediction-markets/maker-rebate/payouts: + post: + tags: + - Rewards + summary: List maker-rebate payouts + description: | + Returns the authenticated account's Maker Rebate payout history. Most recent payout first. + + Pagination is read from the `limit` and `offset` query parameters: `limit` is clamped to `[1, 100]` (default 50), `offset` is clamped to `[0, +∞)` (default 0). + + Requires authentication with `OrderStatus` permission. Returns `503` when the program is disabled. + operationId: listMakerRebatePayouts + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + parameters: + - name: limit + in: query + description: Maximum number of payouts to return (default 50, clamped to [1, 100]). + required: false + schema: + type: integer + default: 50 + minimum: 1 + maximum: 100 + - name: offset + in: query + description: Number of payouts to skip (default 0). + required: false + schema: + type: integer + default: 0 + minimum: 0 + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/MakerRebatePayoutsResponse' + examples: + samplePayouts: + summary: Two recent payouts + value: + payouts: + - id: 9182 + total_volume_usd: "12450.00" + total_rebate_usd: "6.23" + total_fill_count: 187 + status: "PAID" + paid_at: "2026-05-20T21:00:00Z" + created_at: "2026-05-20T20:55:12Z" + - id: 9173 + total_volume_usd: "8920.50" + total_rebate_usd: "4.46" + total_fill_count: 124 + status: "PAID" + paid_at: "2026-05-19T21:00:00Z" + created_at: "2026-05-19T20:55:08Z" + '401': + $ref: '#/components/responses/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "An unexpected error occurred" + '503': + description: Maker rebate program is not currently available + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "Maker rebate program is not currently available" + + /v1/prediction-markets/maker-rebate/summary/total: + get: + tags: + - Rewards + summary: Get maker-rebate lifetime summary + description: | + Returns lifetime totals for the authenticated account's Maker Rebate payouts. When both `dateFrom` and `dateTo` are provided, the totals are restricted to payouts paid within that inclusive Eastern Time window. + + Either provide both date parameters or omit both. Dates must be in `YYYY-MM-DD` format, `dateTo` must be on or after `dateFrom`, and the range must not exceed 5 years. + + Requires authentication with `OrderStatus` permission. Returns `503` when the program is disabled. + operationId: getMakerRebateLifetimeSummary + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + parameters: + - name: dateFrom + in: query + description: Inclusive start of the payout date window (`YYYY-MM-DD`, Eastern Time). Must be provided together with `dateTo`. + required: false + schema: + type: string + format: date + example: "2026-04-01" + - name: dateTo + in: query + description: Inclusive end of the payout date window (`YYYY-MM-DD`, Eastern Time). Must be on or after `dateFrom` and within 5 years of it. + required: false + schema: + type: string + format: date + example: "2026-05-01" + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/MakerRebateLifetimeSummary' + examples: + lifetime: + summary: Lifetime totals (no date filter) + value: + total_earned_usd: "152.40" + total_fill_count: 4218 + total_volume_usd: "304800.00" + payout_count: 27 + first_payout_date: "2026-03-19" + last_payout_date: "2026-05-20" + emptyHistory: + summary: Account has never received a payout + value: + total_earned_usd: "0" + total_fill_count: 0 + total_volume_usd: "0" + payout_count: 0 + first_payout_date: null + last_payout_date: null + '400': + description: Invalid date parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "BAD_REQUEST" + message: "date_to must be on or after date_from" + '401': + $ref: '#/components/responses/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "INTERNAL_ERROR" + message: "An unexpected error occurred" + '503': + description: Maker rebate program is not currently available + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "SERVICE_UNAVAILABLE" + message: "Maker rebate program is not currently available" + + /v1/prediction-markets/liquidity-rewards/config: + get: + tags: + - Rewards + summary: Get liquidity-rewards program config + description: | + Returns the Liquidity Rewards program configuration. Public endpoint; no authentication required. + + When the program is fully configured the response includes `max_spread_cents`, `min_payout_threshold_usd`, and `enabled: true`. When the program is not yet fully configured, the response collapses to `{ "enabled": false }` only. + + Returns `503` when the program is not currently available. + operationId: getLiquidityRewardsConfig + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/LiquidityRewardsConfig' + examples: + enabled: + summary: Program enabled and configured + value: + max_spread_cents: 10 + min_payout_threshold_usd: "1.00" + enabled: true + disabledShape: + summary: Program flag on but config incomplete upstream + value: + enabled: false + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "INTERNAL_ERROR" + message: "An unexpected error occurred" + '503': + description: Liquidity rewards program is not currently available + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "SERVICE_UNAVAILABLE" + message: "Liquidity rewards program is not currently available" + + /v1/prediction-markets/liquidity-rewards/events: + get: + tags: + - Rewards + summary: List liquidity-rewards events + description: | + Returns the paginated list of events currently participating in the Liquidity Rewards program. Public endpoint; no authentication required. + + `category` accepts a comma-separated list of category names (whitespace trimmed, empty entries dropped). `sort` controls ordering. `limit` is clamped to `[1, 100]` (default 50); `offset` is clamped to `[0, +∞)` (default 0). `last_score_date` is the most recent date for which scoring data has been written, or `null` when no scoring has run yet. + + Returns `503` when the program is not currently available. + operationId: listLiquidityRewardsEvents + parameters: + - name: category + in: query + description: Comma-separated list of category names. Whitespace is trimmed and empty entries are dropped. + required: false + schema: + type: string + example: "Crypto,Sports" + - name: search + in: query + description: Filter events by title substring (case-insensitive). + required: false + schema: + type: string + - name: sort + in: query + description: Sort order for the returned events. Defaults to `daily_pool_desc`. + required: false + schema: + type: string + default: daily_pool_desc + enum: + - daily_pool_desc + - daily_pool_asc + - ends_soonest + - ends_latest + - title_asc + - title_desc + - category_asc + - category_desc + - competition_asc + - competition_desc + - name: limit + in: query + description: Maximum number of events to return (default 50, clamped to [1, 100]). + required: false + schema: + type: integer + default: 50 + minimum: 1 + maximum: 100 + - name: offset + in: query + description: Number of events to skip (default 0). + required: false + schema: + type: integer + default: 0 + minimum: 0 + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/LiquidityRewardsEventsResponse' + examples: + sampleEvents: + summary: Two scored events + value: + events: + - event_ticker: "BTC2605202100" + title: "BTC above $95,000?" + category: "Crypto" + daily_pool_usd: "500.00" + pool_source: "event_override" + ends_at: "2026-05-20T21:00:00Z" + qualifying_maker_count: 14 + icon_url: "https://example.com/btc.png" + - event_ticker: "FRENCHOPEN-FINAL" + title: "French Open 2026 — Men's Final winner" + category: "Sports" + daily_pool_usd: "250.00" + pool_source: "category_default" + ends_at: "2026-06-07T15:00:00Z" + qualifying_maker_count: 7 + pagination: + limit: 50 + offset: 0 + total: 2 + last_score_date: "2026-05-19" + emptyBeforeScoring: + summary: Program just turned on, no scoring yet + value: + events: [] + pagination: + limit: 50 + offset: 0 + total: 0 + last_score_date: null + '400': + description: Invalid sort or pagination parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "BAD_REQUEST" + message: "sort must be one of: daily_pool_desc, daily_pool_asc, ends_soonest, ends_latest, title_asc, title_desc, category_asc, category_desc, competition_asc, competition_desc (got 'foo')" + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "INTERNAL_ERROR" + message: "An unexpected error occurred" + '503': + description: Liquidity rewards program is not currently available + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "SERVICE_UNAVAILABLE" + message: "Liquidity rewards program is not currently available" + + /v1/prediction-markets/liquidity-rewards/summary/daily: + get: + tags: + - Rewards + summary: Get liquidity-rewards daily summary + description: | + Returns daily Liquidity Rewards payouts for the authenticated account within the requested date window. Both `dateFrom` and `dateTo` are required and must be in `YYYY-MM-DD` format; `dateTo` must be on or after `dateFrom`. + + Each daily entry includes the total USD reward for that day, the payout status (e.g. `PENDING`, `PAID`), the paid-at timestamp (if paid), and per-event score breakdowns showing how the day's reward was distributed across events the account scored on. + + Requires authentication with `OrderStatus` permission. Returns `503` when the program is not currently available. + operationId: getLiquidityRewardsDailySummary + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + parameters: + - name: dateFrom + in: query + description: Inclusive start of the date window (`YYYY-MM-DD`, Eastern Time). + required: true + schema: + type: string + format: date + example: "2026-05-01" + - name: dateTo + in: query + description: Inclusive end of the date window (`YYYY-MM-DD`, Eastern Time). Must be on or after `dateFrom`. + required: true + schema: + type: string + format: date + example: "2026-05-07" + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/LiquidityRewardsDailySummaryResponse' + examples: + sampleWeek: + summary: One week of daily summaries + value: + daily_summaries: + - payout_date: "2026-05-07" + total_reward_usd: "12.45" + payout_status: "PAID" + paid_at: "2026-05-08T21:00:00Z" + events: + - event_id: 1234567890 + event_name: "BTC above $95,000?" + category_name: "Crypto" + normalized_score: "0.4521" + snapshot_count: 1180 + total_snapshots: 1440 + event_reward_usd: "8.20" + - event_id: 9876543210 + event_name: "ETH above $4,000?" + category_name: "Crypto" + normalized_score: "0.2341" + snapshot_count: 920 + total_snapshots: 1440 + event_reward_usd: "4.25" + - payout_date: "2026-05-06" + total_reward_usd: "0" + payout_status: "ZERO_AMOUNT" + paid_at: null + events: [] + '400': + description: Invalid date parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "date_to must be on or after date_from" + '401': + $ref: '#/components/responses/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "An unexpected error occurred" + '503': + description: Liquidity rewards program is not currently available + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "Liquidity incentive program is not currently available" + + /v1/prediction-markets/liquidity-rewards/summary/total: + get: + tags: + - Rewards + summary: Get liquidity-rewards lifetime summary + description: | + Returns lifetime totals for the authenticated account's Liquidity Rewards payouts. When both `dateFrom` and `dateTo` are provided, the totals are restricted to payouts paid within that inclusive Eastern Time window. + + Either provide both date parameters or omit both. Dates must be in `YYYY-MM-DD` format, `dateTo` must be on or after `dateFrom`, and the range must not exceed 5 years. + + Requires authentication with `OrderStatus` permission. Returns `503` when the program is not currently available. + operationId: getLiquidityRewardsLifetimeSummary + security: + - apiKey: [] + payloadAuth: [] + signatureAuth: [] + parameters: + - name: dateFrom + in: query + description: Inclusive start of the payout date window (`YYYY-MM-DD`, Eastern Time). Must be provided together with `dateTo`. + required: false + schema: + type: string + format: date + example: "2026-04-01" + - name: dateTo + in: query + description: Inclusive end of the payout date window (`YYYY-MM-DD`, Eastern Time). Must be on or after `dateFrom` and within 5 years of it. + required: false + schema: + type: string + format: date + example: "2026-05-01" + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/LiquidityRewardsLifetimeSummary' + examples: + lifetime: + summary: Lifetime totals + value: + total_earned_usd: "84.20" + payout_count: 12 + first_payout_date: "2026-05-08" + last_payout_date: "2026-05-20" + emptyHistory: + summary: Account has never received a payout + value: + total_earned_usd: "0" + payout_count: 0 + first_payout_date: null + last_payout_date: null + '400': + description: Invalid date parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "BAD_REQUEST" + message: "date_to must be on or after date_from" + '401': + $ref: '#/components/responses/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "INTERNAL_ERROR" + message: "An unexpected error occurred" + '503': + description: Liquidity rewards program is not currently available + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + error: "SERVICE_UNAVAILABLE" + message: "Liquidity rewards program is not currently available" + +components: + securitySchemes: + apiKey: + type: apiKey + in: header + name: X-GEMINI-APIKEY + description: Gemini API key with appropriate permissions + payloadAuth: + type: apiKey + in: header + name: X-GEMINI-PAYLOAD + description: Base64-encoded private REST payload. See Gemini private REST authentication. + signatureAuth: + type: apiKey + in: header + name: X-GEMINI-SIGNATURE + description: Hex HMAC-SHA384 signature of the payload using the API secret. + + parameters: + Limit: + name: limit + in: query + description: Maximum number of results to return (max 500) + schema: + type: integer + default: 50 + minimum: 1 + maximum: 500 + Offset: + name: offset + in: query + description: Number of results to skip for pagination + schema: + type: integer + default: 0 + minimum: 0 + SportFilter: + name: sport + in: query + description: Filter by `sportsMarket.sport`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`; valid combinations with no matching events return an empty result. + schema: + type: array + items: + $ref: '#/components/schemas/SportsMarketSport' + style: form + explode: true + SportsMarketTypeFilter: + name: sports_market_type + in: query + description: Filter by `sportsMarket.type`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + schema: + type: array + items: + $ref: '#/components/schemas/SportsMarketType' + style: form + explode: true + SportsMarketSubjectFilter: + name: sports_market_subject + in: query + description: Filter by `sportsMarket.subject`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + schema: + type: array + items: + $ref: '#/components/schemas/SportsMarketSubject' + style: form + explode: true + SportsMarketScopeFilter: + name: sports_market_scope + in: query + description: Filter by `sportsMarket.scope.type`. Repeat the parameter to match any supplied value (OR). Ordinal and range qualifiers are not inferred by this filter. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + schema: + type: array + items: + $ref: '#/components/schemas/SportsMarketScopeType' + style: form + explode: true + SportsMarketMetricFilter: + name: sports_market_metric + in: query + description: Filter by `sportsMarket.metric`. Repeat the parameter to match any supplied value (OR). A metric can be queried without `sport`; use `sport` when its sport-specific meaning matters. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + schema: + type: array + items: + $ref: '#/components/schemas/SportsMarketMetric' + style: form + explode: true + + responses: + BadRequest: + description: Invalid request parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + Unauthorized: + description: Authentication required or invalid credentials + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + InternalError: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + ServiceUnavailable: + description: Prediction markets feature is temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + schemas: + Error: + type: object + properties: + error: + type: string + description: Error code + example: "InvalidInput" + message: + type: string + description: Human-readable error message + example: "orderId is required" + + PredictionMarketsError: + type: object + additionalProperties: false + required: + - error + properties: + error: + type: string + description: Prediction Markets error class + example: "InvalidInput" + field: + type: string + description: Request field associated with the error, when available + example: "orders" + message: + type: string + description: Human-readable error detail, when available + example: "orders must contain between 1 and 20 entries" + + AuthErrorResponse: + type: object + additionalProperties: false + required: + - result + - reason + - message + properties: + result: + type: string + enum: [error] + reason: + type: string + description: Authentication or authorization error class + example: "MissingNonce" + message: + type: string + description: Human-readable authentication or authorization detail + example: "Must provide unique monotonic increasing 'nonce' field in payload" + + AccountGroupBlockedError: + type: object + additionalProperties: false + required: + - error + - code + properties: + error: + type: string + enum: ["This account is not permitted to trade prediction markets"] + code: + type: string + enum: [ACCOUNT_GROUP_BLOCKED] + + TermsNotAcceptedError: + type: object + additionalProperties: false + required: + - error + - message + properties: + error: + type: string + enum: [TERMS_NOT_ACCEPTED] + message: + type: string + enum: ["Prediction markets terms must be accepted before placing orders"] + + RestrictedSellOnlyError: + type: object + additionalProperties: false + required: + - error + - message + properties: + error: + type: string + enum: [ACCOUNT_RESTRICTED_SELL_ONLY] + message: + type: string + enum: ["Your account is restricted to selling existing positions; buying is not permitted."] + + PredictionMarketsTerms: + type: object + required: + - termsType + - version + - content + - updatedAt + properties: + termsType: + type: string + description: Terms type identifier + example: "PredictionsMarket" + version: + type: integer + description: Latest terms version + example: 3 + content: + type: string + description: Terms content to display before acceptance + example: "These are the prediction market terms." + updatedAt: + type: string + format: date-time + description: UTC timestamp when the terms content was last updated + example: "2026-05-18T17:00:00Z" + + PredictionMarketsTermsStatus: + type: object + required: + - hasAcceptedLatest + properties: + hasAcceptedLatest: + type: boolean + description: Whether the account group has accepted the latest configured Prediction Markets terms + example: false + acceptedVersion: + type: integer + nullable: true + description: Latest terms version accepted by the account group, if any + example: 2 + latestVersion: + type: integer + nullable: true + description: Latest configured Prediction Markets terms version, if available + example: 3 + + AcceptPredictionMarketsTermsResponse: + type: object + required: + - success + properties: + success: + type: boolean + example: true + + MarketStatus: + type: string + enum: [approved, active, closed, under_review, settled, invalid] + description: Status of a prediction market + + MarketType: + type: string + enum: [binary, categorical] + description: Type of prediction market + + SportsMarketSport: + type: string + enum: [american_football, athletics, australian_rules_football, baseball, basketball, boxing, chess, cricket, cycling, darts, esports, golf, hockey, lacrosse, mixed_martial_arts, motorsports, rugby, sailing, soccer, tennis] + description: Sport whose rules give the market's scope and metric their sport-specific meaning. + + SportsMarketType: + type: string + enum: [moneyline, spread, total, prop, correct_score, to_advance, futures, other] + description: Conventional sports-market family. `subject`, `scope`, and `metric` provide detail within the family. This classification is independent of the event's structural `type` (`binary` or `categorical`). + + SportsMarketSubject: + type: string + enum: [contest, team, player, participant, other] + description: What the market is about. `participant` covers non-player entrants such as drivers and horses. + + SportsMarketScopeType: + type: string + enum: [full_contest, regulation, half, quarter, period, inning, team_innings, over, powerplay, set, game, round, hole, match_day, session, super_over, race, sprint, qualifying, practice, stage, lap, series, season, tournament, competition, other] + description: Unit covered by the market. `full_contest` follows the market's official final-result rules; `regulation` covers scheduled regulation play only. Ordinal and range qualifiers are represented separately on `SportsMarketScope`. + + SportsMarketMetric: + type: string + description: Statistic measured by the market. Interpret shared metric names using `sportsMarket.sport`. + enum: + - aces + - assists + - balls_faced + - birdies + - blocked_shots + - blocks + - bogeys + - boundaries + - break_points_won + - cards + - catches + - clean_sheets + - completed_passes + - control_time + - corners + - defensive_rebounds + - double_double + - double_faults + - doubles + - eagles + - earned_runs + - errors + - faceoff_wins + - fairways_hit + - fantasy_points + - fastest_lap + - field_goals_made + - finishing_position + - fouls + - fours + - free_throws_made + - fumbles + - games + - goals + - goals_allowed + - greens_in_regulation + - grid_position + - hits + - hits_allowed + - hits_runs_rbis + - holes_in_one + - home_runs + - innings_pitched + - interceptions_thrown + - kicking_points + - knockdowns + - laps_completed + - laps_led + - lap_time + - longest_pass_completion + - longest_reception + - longest_rush + - maiden_overs + - offensive_rebounds + - offsides + - pars + - passes + - pass_attempts + - pass_completions + - passing_touchdowns + - passing_yards + - penalty_minutes + - pitching_outs_recorded + - pit_stops + - points + - points_assists + - points_rebounds + - points_rebounds_assists + - positions_gained + - power_play_points + - putts + - qualifying_position + - rebounds + - rebounds_assists + - receiving_touchdowns + - receiving_yards + - receptions + - red_cards + - retirements + - rounds + - runs + - runs_batted_in + - runs_conceded + - rush_attempts + - rushing_touchdowns + - rushing_yards + - sacks + - safety_cars + - saves + - sets + - shots + - shots_on_goal + - shots_on_target + - shutouts + - significant_strikes + - singles + - sixes + - steals + - stolen_bases + - strokes + - strikeouts + - submission_attempts + - tackles + - takedowns + - three_pointers_made + - tiebreaks_won + - total_bases + - total_points_won + - total_strikes + - touchdowns + - triples + - triple_double + - turnovers + - walks + - wickets + - wins + - yellow_cards + - other + + SportsMarketScope: + type: object + additionalProperties: false + description: Settlement scope. `ordinal` identifies one unit; `start` and `end` identify an inclusive range of units. + required: + - type + properties: + type: + $ref: '#/components/schemas/SportsMarketScopeType' + ordinal: + type: integer + format: int32 + minimum: 0 + description: Optional ordinal within the scope type, such as half `1` or quarter `4`. + start: + type: integer + format: int32 + minimum: 0 + description: Optional inclusive start of a scope range, such as inning `1`. + end: + type: integer + format: int32 + minimum: 0 + description: Optional inclusive end of a scope range, such as inning `5`. + + SportsMarket: + type: object + additionalProperties: false + description: Atomic sports-market classification shared by every contract grouped under the event. Present only for sports events. All fields except `metric` are required together. + required: + - sport + - type + - subject + - scope + properties: + sport: + $ref: '#/components/schemas/SportsMarketSport' + type: + $ref: '#/components/schemas/SportsMarketType' + subject: + $ref: '#/components/schemas/SportsMarketSubject' + scope: + $ref: '#/components/schemas/SportsMarketScope' + metric: + $ref: '#/components/schemas/SportsMarketMetric' + + OrderType: + type: string + enum: [limit, stop-limit] + description: Order type. `stop-limit` orders require a `stopPrice` that triggers a limit order at `price` when the market reaches the trigger. + + OrderSide: + type: string + enum: [buy, sell] + + Outcome: + type: string + enum: ["yes", "no"] + description: The outcome being traded (Yes or No) + + TimeInForce: + type: string + enum: [good-til-cancel, immediate-or-cancel, fill-or-kill] + default: good-til-cancel + description: | + Order execution behavior: + - `good-til-cancel` - Order remains active until filled or cancelled (default) + - `immediate-or-cancel` - Fill immediately or cancel remaining + - `fill-or-kill` - Fill entire order immediately or cancel + + OrderStatus: + type: string + enum: [open, filled, cancelled] + + PositionStatus: + type: string + enum: [active, resolved, cancelled] + + Pagination: + type: object + properties: + limit: + type: integer + example: 50 + offset: + type: integer + example: 0 + total: + type: integer + example: 100 + + PaginationSimple: + type: object + properties: + limit: + type: integer + offset: + type: integer + count: + type: integer + description: Number of items in current response + + OrderBook: + type: object + properties: + bids: + type: array + items: + $ref: '#/components/schemas/OrderBookEntry' + asks: + type: array + items: + $ref: '#/components/schemas/OrderBookEntry' + + OrderBookEntry: + type: object + properties: + side: + $ref: '#/components/schemas/OrderSide' + price: + type: string + example: "0.65" + quantity: + type: string + example: "1000" + + OrderBookDepth: + type: object + properties: + bids: + type: array + items: + $ref: '#/components/schemas/OrderBookLevel' + asks: + type: array + items: + $ref: '#/components/schemas/OrderBookLevel' + lastUpdateTime: + type: string + format: date-time + + OrderBookLevel: + type: object + properties: + price: + type: string + quantity: + type: string + orderCount: + type: integer + + Contract: + type: object + description: | + Contract quantity and price validation is instrument-specific. Clients must validate order quantities and prices against the returned increment and minimum fields rather than assuming a fixed grid. + properties: + id: + type: string + label: + type: string + description: Human-readable label for the contract's YES-space proposition (e.g., "SOL > $90") + abbreviatedName: + type: string + nullable: true + description: Short form label (e.g., ">$90") + description: + type: object + description: Rich text description + prices: + $ref: '#/components/schemas/ContractPrices' + color: + type: string + nullable: true + status: + $ref: '#/components/schemas/MarketStatus' + imageUrl: + type: string + nullable: true + priceHistory: + type: array + nullable: true + items: + $ref: '#/components/schemas/PricePoint' + createdAt: + type: string + format: date-time + expiryDate: + type: string + format: date-time + nullable: true + resolutionSide: + $ref: '#/components/schemas/Outcome' + resolvedAt: + type: string + format: date-time + nullable: true + termsAndConditionsUrl: + type: string + ticker: + type: string + instrumentSymbol: + type: string + quantityIncrement: + type: string + nullable: true + description: Contract quantity grid from instrument refdata (for example, "0.01"). + quantityMinimum: + type: string + nullable: true + description: Minimum contract quantity from instrument refdata (for example, "1.00"). + priceIncrement: + type: string + nullable: true + description: Contract price grid from instrument refdata (for example, "0.0001"). + quoteAssetPrecision: + type: integer + nullable: true + description: Decimal places supported by the instrument's quote asset. + priceMinimum: + type: string + nullable: true + description: Minimum contract price and anchor for the instrument price grid (for example, "0.0001"). + effectiveDate: + type: string + format: date-time + nullable: true + marketState: + type: string + nullable: true + description: Trading state of the contract + enum: [open, closed] + sortOrder: + type: integer + nullable: true + description: Display order within the event + strike: + $ref: '#/components/schemas/Strike' + source: + type: string + nullable: true + deprecated: true + description: 'Deprecated: use the event-level `sourceDetails` (`agency` + `index`) instead. Data source identifier for price observation (e.g., "GRR-KAIKO_BTCUSD_60S"). Present for crypto Up/Down contracts.' + example: "GRR-KAIKO_BTCUSD_60S" + settlementValue: + type: string + nullable: true + description: The observed settlement price. Only present after the contract is settled. + example: "87654.32" + + StrikeType: + type: string + description: >- + Strike or condition inequality type for contract threshold evaluation. + - `reference`: Crypto Up/Down reference strike price captured at `availableAt` time. + - `above`: Higher/Lower contract threshold. + - `spread`: Point, run, or goal handicap spread line. + - `over`: Total or prop threshold evaluated as strict greater than (`>`). + - `over_or_equal`: Total or prop threshold evaluated as greater than or equal to (`>=`). + - `under`: Total or prop threshold evaluated as strict less than (`<`). + - `under_or_equal`: Position, rank, or total threshold evaluated as less than or equal to (`<=`). + enum: + - reference + - above + - spread + - over + - over_or_equal + - under + - under_or_equal + example: "spread" + + Strike: + type: object + description: Strike price or contract threshold information for Up/Down crypto contracts and sports prediction market contracts. + properties: + value: + type: string + nullable: true + description: >- + The strike price value. Null for "reference" type strikes where the value is determined at availableAt time. + For sports contracts, this represents the derived numeric strike value (e.g. spread margin, total line, or position/rank threshold). + example: "87500.00" + type: + $ref: '#/components/schemas/StrikeType' + availableAt: + type: string + format: date-time + nullable: true + description: When the strike price becomes available + example: "2026-03-27T19:45:00.000Z" + + SourceDetails: + type: object + nullable: true + description: >- + Structured data source information for price observation. Replaces the deprecated + flat `source` string on the event and contract. Present for crypto Up/Down events. + Both fields are omitted when not available. + properties: + agency: + type: string + nullable: true + description: The data provider / vendor name. + example: "Kaiko" + index: + type: string + nullable: true + description: The specific data feed identifier (the value previously carried by the flat `source` field). + example: "GRR-KAIKO_BTCUSD_60S" + + PricePoint: + type: object + properties: + timestamp: + type: string + format: date-time + price: + type: string + + ContractPrices: + type: object + nullable: true + description: Current bid/ask pricing for the contract + properties: + buy: + type: object + description: Buy prices for each outcome + properties: + "yes": + type: string + description: Price to buy YES outcome + example: "0.42" + "no": + type: string + description: Price to buy NO outcome + example: "0.58" + sell: + type: object + description: Sell prices for each outcome + properties: + "yes": + type: string + description: Price to sell YES outcome + example: "0.42" + "no": + type: string + description: Price to sell NO outcome + example: "0.58" + bestBid: + type: string + nullable: true + description: Highest buy offer + example: "0.49" + bestAsk: + type: string + nullable: true + description: Lowest sell offer + example: "0.54" + lastTradePrice: + type: string + nullable: true + description: Most recent transaction price + example: "0.75" + + Event: + type: object + description: A prediction market event containing one or more tradeable contracts + properties: + id: + type: string + title: + type: string + example: "Will Bitcoin reach $100k by end of 2028?" + slug: + type: string + example: "bitcoin-100k-2028" + description: + type: string + nullable: true + imageUrl: + type: string + nullable: true + type: + $ref: '#/components/schemas/MarketType' + category: + type: string + example: "crypto" + series: + type: string + nullable: true + sportsMarket: + $ref: '#/components/schemas/SportsMarket' + ticker: + type: string + description: The event ticker (e.g., "BTC100K2028") + example: "BTC100K2028" + status: + $ref: '#/components/schemas/MarketStatus' + resolvedAt: + type: string + format: date-time + nullable: true + createdAt: + type: string + format: date-time + contracts: + type: array + description: Tradeable contracts within this event + items: + $ref: '#/components/schemas/Contract' + contractOrderbooks: + type: object + additionalProperties: + $ref: '#/components/schemas/OrderBook' + volume: + type: string + description: Total trading volume in USD + example: "125000.00" + liquidity: + type: string + description: Total liquidity in USD + example: "50000.00" + tags: + type: array + nullable: true + items: + type: string + effectiveDate: + type: string + format: date-time + expiryDate: + type: string + format: date-time + nullable: true + subcategory: + $ref: '#/components/schemas/Subcategory' + source: + type: string + nullable: true + deprecated: true + description: 'Deprecated: use `sourceDetails` (`agency` + `index`) instead. Data source identifier for price observation. Aggregated from contracts for crypto Up/Down events.' + example: "GRR-KAIKO_BTCUSD_60S" + sourceDetails: + $ref: '#/components/schemas/SourceDetails' + settlement: + $ref: '#/components/schemas/Settlement' + + Subcategory: + type: object + nullable: true + description: Nested category information for the event + properties: + id: + type: integer + description: Category identifier + example: 35 + slug: + type: string + description: URL-friendly category identifier + example: "crypto_solana" + name: + type: string + description: Display name + example: "Solana" + path: + type: array + description: Category hierarchy path + items: + type: string + example: ["Crypto", "Solana"] + + Settlement: + type: object + description: Settlement information for resolved events + properties: + value: + type: string + nullable: true + description: The observed settlement value (e.g., the price at expiry for crypto contracts) + example: "87654.32" + + EventsResponse: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Event' + pagination: + $ref: '#/components/schemas/Pagination' + + ContractMetadata: + type: object + properties: + contractId: + type: string + contractName: + type: string + contractTicker: + type: string + eventTicker: + type: string + eventName: + type: string + category: + type: string + contractStatus: + type: string + eventType: + type: string + description: Event type ("binary" or "categorical") + expiryDate: + type: string + format: date-time + nullable: true + resolvedAt: + type: string + format: date-time + nullable: true + resolutionSide: + type: string + nullable: true + description: Winning outcome if resolved ("yes" or "no") + parentEventTicker: + type: string + nullable: true + description: Parent event ticker for sub-events + startTime: + type: string + format: date-time + nullable: true + description: Start datetime (ISO 8601) + + ComboLeg: + type: object + required: + - comboId + - legIndex + - contractId + - requiredOutcome + properties: + comboId: + type: integer + format: int64 + description: Internal ID of the parent combo contract + example: 456 + legIndex: + type: integer + description: Zero-based position of this leg in the combo + example: 0 + contractId: + type: string + description: Internal ID of the underlying single contract, represented as a decimal string + example: "101" + requiredOutcome: + type: string + enum: ["Yes", "No"] + description: The outcome this leg must settle for the combo to settle YES + example: "Yes" + legOutcome: + type: string + nullable: true + description: The outcome this leg has settled to, if resolved (`"Yes"` or `"No"`). Null while the leg is still active. + example: null + resolvedAt: + type: string + format: date-time + nullable: true + description: UTC timestamp when this leg resolved. Null while still active. + example: null + contract: + nullable: true + allOf: + - $ref: '#/components/schemas/ContractMetadata' + description: Full metadata for the underlying single contract + + ComboResponse: + type: object + required: + - contract + - legs + properties: + contract: + allOf: + - $ref: '#/components/schemas/ContractMetadata' + description: Metadata for the combo contract itself (ticker, status, expiry, etc.) + legs: + type: array + description: Ordered list of legs that make up this combo + items: + $ref: '#/components/schemas/ComboLeg' + + ListCombosResponse: + type: object + required: + - combos + - pagination + properties: + combos: + type: array + description: List of combo contracts matching the query + items: + $ref: '#/components/schemas/ComboResponse' + pagination: + allOf: + - $ref: '#/components/schemas/Pagination' + + CreateComboRequest: + type: object + description: A canonical combo definition. The authenticated account is derived from the signed request and is not a request field. + required: + - legs + properties: + legs: + type: array + description: Two to six distinct underlying contract legs. The service canonicalizes their complete set, so leg order does not create a distinct combo. + minItems: 2 + maxItems: 6 + items: + $ref: '#/components/schemas/CreateComboLeg' + + CreateComboLeg: + type: object + required: + - contractId + - requiredOutcome + properties: + contractId: + type: string + description: Underlying contract ID as a decimal string. + example: "101" + requiredOutcome: + type: string + enum: ["Yes", "No"] + description: Required settlement outcome for this leg. + example: "Yes" + + CreateComboResponse: + type: object + required: + - combo + - alreadyExisted + properties: + combo: + $ref: '#/components/schemas/ComboSummary' + alreadyExisted: + type: boolean + description: "`false` when this request created the canonical combo; `true` when the canonical combo already existed." + + ComboSummary: + type: object + required: + - id + - canonicalLegKey + - legCount + - instrumentRegistered + - legs + properties: + id: + type: integer + format: int64 + description: Internal combo ID. + example: 456 + canonicalLegKey: + type: string + description: Canonical identity of the complete combo leg set. + example: "101:Yes|202:No" + legCount: + type: integer + format: int32 + description: Number of legs in the combo. + example: 2 + displayName: + type: string + description: Human-readable combo name, when available. + status: + type: string + description: Current combo status, when available. + instrumentId: + type: integer + format: int64 + description: Associated instrument ID, when available. + instrumentSymbol: + type: string + description: Associated instrument symbol, when available. + example: "GEMI-CMB-0526-A7F3B2C1D4E5" + instrumentRegistered: + type: boolean + description: Whether the combo has been registered with an instrument symbol. + latestExpiryDate: + type: string + format: date-time + description: Latest expiry among the underlying legs, when available. + createdAt: + type: string + format: date-time + description: Creation time, when available. + updatedAt: + type: string + format: date-time + description: Most recent update time, when available. + legs: + type: array + description: Canonically ordered combo legs. + items: + $ref: '#/components/schemas/ComboSummaryLeg' + + ComboSummaryLeg: + type: object + required: + - comboId + - legIndex + - contractId + - requiredOutcome + properties: + comboId: + type: integer + format: int64 + description: Parent combo ID. + legIndex: + type: integer + format: int32 + description: Zero-based leg position in canonical order. + contractId: + type: string + description: Underlying contract ID as a decimal string. + requiredOutcome: + type: string + enum: ["Yes", "No"] + description: Required settlement outcome for the leg. + legOutcome: + type: string + enum: ["Yes", "No"] + nullable: true + description: Settled outcome for the leg, when resolved. + resolvedAt: + type: string + format: date-time + nullable: true + description: Resolution time for the leg, when resolved. + contract: + allOf: + - $ref: '#/components/schemas/ContractMetadata' + description: Underlying contract metadata, when available. + + ComboWriteError: + type: object + required: + - error + - message + properties: + error: + type: string + description: Error class. + example: "InvalidInput" + code: + type: string + description: Machine-readable code for validation or missing-leg errors, when available. + example: "COMBO_VALIDATION_ERROR" + message: + type: string + description: Human-readable error detail. + example: "a combo needs 2-6 legs" + + OrderRequest: + type: object + required: + - symbol + - orderType + - side + - quantity + - price + - outcome + properties: + symbol: + type: string + description: Contract instrument symbol + example: "GEMI-FEDJAN26-DN25" + orderType: + $ref: '#/components/schemas/OrderType' + side: + $ref: '#/components/schemas/OrderSide' + quantity: + type: string + format: decimal + description: Number of contracts + example: "100" + price: + type: string + format: decimal + description: Limit price (0-1 range) + example: "0.65" + stopPrice: + type: string + format: decimal + description: The price to trigger a stop-limit order (0-1 range). Only available for stop-limit orders. See [Stop-Limit Orders](#operation/placeOrder) above for `stopPrice`/`price` constraints. + example: "0.60" + outcome: + $ref: '#/components/schemas/Outcome' + timeInForce: + $ref: '#/components/schemas/TimeInForce' + makerOrCancel: + type: boolean + description: Set to `true` to require maker-only behavior. If the order would immediately take liquidity, the order is cancelled instead of filling. + default: false + + PlaceOrderBatchRequest: + type: object + required: + - orders + properties: + orders: + type: array + minItems: 1 + maxItems: 20 + description: Orders to submit. Every entry is validated before any order is submitted. All orders use the account associated with the authenticated request. + items: + $ref: '#/components/schemas/OrderRequest' + + BatchOrderResponse: + type: object + description: An accepted order returned for one batch entry. + required: + - orderId + - status + - symbol + - side + - outcome + - orderType + - timeInForce + - quantity + - filledQuantity + - remainingQuantity + - price + - createdAt + - updatedAt + properties: + orderId: + type: integer + format: int64 + example: 12345678 + hashOrderId: + type: string + description: Hashed order ID; omitted when unavailable + clientOrderId: + type: string + description: Client-provided order ID; omitted when unavailable + globalOrderId: + type: string + description: Global order ID; omitted when unavailable + status: + type: string + enum: [open, filled, cancelled, closed] + symbol: + type: string + side: + $ref: '#/components/schemas/OrderSide' + outcome: + $ref: '#/components/schemas/Outcome' + orderType: + $ref: '#/components/schemas/OrderType' + timeInForce: + type: string + enum: [good-til-cancel, immediate-or-cancel, fill-or-kill, maker-or-cancel] + quantity: + type: string + description: Original order quantity + filledQuantity: + type: string + description: Amount filled so far + remainingQuantity: + type: string + description: Amount remaining to fill + price: + type: string + description: Limit price + stopPrice: + type: string + description: Stop trigger price; omitted unless populated for a `stop-limit` order + avgExecutionPrice: + type: string + description: Average price of fills; omitted when unavailable + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + cancelledAt: + type: string + format: date-time + description: Cancellation time; omitted unless the order was cancelled + contractMetadata: + $ref: '#/components/schemas/ContractMetadata' + promoCashApplied: + type: string + description: Promotional cash reserved or applied to the order; omitted when unavailable + fundsOnHold: + type: string + description: Cash reserved for the unfilled portion of a resting buy order; omitted when unavailable + + PlaceOrderBatchSuccessResult: + type: object + additionalProperties: false + required: + - order + properties: + order: + $ref: '#/components/schemas/BatchOrderResponse' + + PlaceOrderBatchErrorResult: + type: object + additionalProperties: false + required: + - error + - message + properties: + error: + type: string + description: Error class for a rejected entry + example: "InsufficientFunds" + message: + type: string + description: Human-readable detail for a rejected entry + example: "Insufficient funds" + + PlaceOrderBatchResult: + description: Exactly one outcome is present. Accepted entries contain `order`; rejected entries contain `error` and `message`. + oneOf: + - $ref: '#/components/schemas/PlaceOrderBatchSuccessResult' + - $ref: '#/components/schemas/PlaceOrderBatchErrorResult' + + PlaceOrderBatchResponse: + type: object + required: + - results + properties: + results: + type: array + minItems: 1 + maxItems: 20 + description: One result for each submitted order, in request order. + items: + $ref: '#/components/schemas/PlaceOrderBatchResult' + + CancelOrderBatchRequest: + type: object + required: + - orderIds + properties: + orderIds: + type: array + minItems: 1 + maxItems: 20 + description: Order IDs to cancel. Each ID may be an integer or a quoted numeric string. All IDs are validated before any cancellation is attempted. + items: + oneOf: + - type: integer + format: int64 + example: 12345678 + - type: string + pattern: '^\d+$' + example: "12345678" + + CancelOrderBatchSuccessResult: + type: object + additionalProperties: false + required: + - orderId + - result + properties: + orderId: + type: integer + format: int64 + description: Order ID from the corresponding request entry. + example: 12345678 + result: + type: string + enum: [ok] + + CancelOrderBatchErrorResult: + type: object + additionalProperties: false + required: + - orderId + - error + - message + properties: + orderId: + type: integer + format: int64 + description: Order ID from the corresponding request entry. + example: 12345678 + error: + type: string + description: Error class for a rejected cancellation + example: "OrderNotFound" + message: + type: string + description: Human-readable detail for a rejected cancellation + example: "Order 12345678 not found" + + CancelOrderBatchResult: + description: Exactly one outcome is present. Successful entries contain `orderId` and `result`; rejected entries contain `orderId`, `error`, and `message`. + oneOf: + - $ref: '#/components/schemas/CancelOrderBatchSuccessResult' + - $ref: '#/components/schemas/CancelOrderBatchErrorResult' + + CancelOrderBatchResponse: + type: object + required: + - results + properties: + results: + type: array + minItems: 1 + maxItems: 20 + description: One result for each requested cancellation, in request order. + items: + $ref: '#/components/schemas/CancelOrderBatchResult' + + OrderResponse: + type: object + properties: + orderId: + type: integer + format: int64 + example: 12345678 + hashOrderId: + type: string + nullable: true + clientOrderId: + type: string + nullable: true + globalOrderId: + type: string + nullable: true + status: + $ref: '#/components/schemas/OrderStatus' + symbol: + type: string + side: + $ref: '#/components/schemas/OrderSide' + outcome: + $ref: '#/components/schemas/Outcome' + orderType: + $ref: '#/components/schemas/OrderType' + quantity: + type: string + description: Original order quantity + filledQuantity: + type: string + description: Amount filled so far + remainingQuantity: + type: string + description: Amount remaining to fill + price: + type: string + description: Limit price + stopPrice: + type: string + nullable: true + description: Stop trigger price (populated for `stop-limit` orders) + avgExecutionPrice: + type: string + nullable: true + description: Average price of fills + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + cancelledAt: + type: string + format: date-time + nullable: true + contractMetadata: + $ref: '#/components/schemas/ContractMetadata' + + OrdersResponse: + type: object + properties: + orders: + type: array + items: + $ref: '#/components/schemas/OrderResponse' + pagination: + $ref: '#/components/schemas/PaginationSimple' + + # QuoteByQuantityResponse: + # type: object + # properties: + # symbol: + # type: string + # quantity: + # type: string + # description: Requested quantity + # bestPrice: + # type: string + # description: Best available price + # executionPrice: + # type: string + # description: Expected execution price + # estimatedSpend: + # type: string + # description: Estimated total spend before fees + # estimatedFees: + # type: string + # description: Estimated fees + # totalCost: + # type: string + # description: Total cost including fees + # liquidity: + # type: string + # description: Available liquidity + # priceImpact: + # type: string + # nullable: true + # description: Expected price impact + # marketDepth: + # $ref: '#/components/schemas/OrderBookDepth' + # warning: + # type: string + # nullable: true + # description: Warning message if applicable + # quoteExpiry: + # type: string + # format: date-time + # description: When this quote expires + + # QuoteBySpendResponse: + # type: object + # properties: + # symbol: + # type: string + # totalSpend: + # type: string + # description: Requested spend amount + # bestPrice: + # type: string + # executionPrice: + # type: string + # estimatedQuantity: + # type: string + # description: Estimated quantity for the spend + # estimatedFees: + # type: string + # totalCost: + # type: string + # liquidity: + # type: string + # priceImpact: + # type: string + # nullable: true + # marketDepth: + # $ref: '#/components/schemas/OrderBookDepth' + # warning: + # type: string + # nullable: true + # quoteExpiry: + # type: string + # format: date-time + + Position: + type: object + properties: + symbol: + type: string + instrumentId: + type: integer + format: int64 + totalQuantity: + type: string + description: Total position size + quantityOnHold: + type: string + description: Quantity currently on hold from open orders + avgPrice: + type: string + description: Average entry price + outcome: + $ref: '#/components/schemas/Outcome' + contractMetadata: + $ref: '#/components/schemas/ContractMetadata' + prices: + $ref: '#/components/schemas/PositionPrices' + resolutionSide: + type: string + nullable: true + description: Winning outcome ("yes" or "no") if the contract has resolved + isAboveAutoStartThreshold: + type: boolean + description: Whether the position is above the auto-start threshold + isLive: + type: boolean + description: Whether the market is currently live/active + realizedPl: + type: string + nullable: true + description: Realized profit/loss from sells + marketValue: + type: string + description: Mark-to-market value of the position in USD at the current sell price (bestBid for YES, bestAsk for NO). **Absent** from the response when the held outcome has no live sell quote (no liquidity to sell into) — surface a no-liquidity state rather than a price the user cannot transact at. `lastTradePrice` is still returned for display. Treat as `Optional`. + example: "65.00" + unrealizedPnl: + type: string + description: Unrealized P&L in USD (`marketValue - costBasis`). **Absent** whenever `marketValue` is absent. Treat as `Optional`. + example: "12.50" + unrealizedPct: + type: number + format: double + description: Unrealized P&L as a percentage of cost basis. Expressed as a percent (e.g. `12.5` represents 12.5%, **not** `0.125`); rounded to 4 decimal places. **Absent** when there is no live sell quote, or when cost basis is zero. Treat as `Optional`. + example: 23.81 + + PositionPrices: + type: object + nullable: true + description: Current bid/ask/last-trade prices for the contract + required: + - buy + - sell + properties: + buy: + type: object + properties: + yes: + type: string + nullable: true + no: + type: string + nullable: true + sell: + type: object + properties: + yes: + type: string + nullable: true + no: + type: string + nullable: true + bestBid: + type: string + nullable: true + bestAsk: + type: string + nullable: true + lastTradePrice: + type: string + nullable: true + + PositionsResponse: + type: object + properties: + positions: + type: array + items: + $ref: '#/components/schemas/Position' + total: + type: integer + nullable: true + description: Total number of positions (for pagination) + + SettledPosition: + type: object + description: A historically settled position in a resolved prediction market contract. + properties: + accountId: + type: integer + format: int64 + description: Account that held the position + instrumentId: + type: integer + format: int64 + description: Unique instrument identifier for the contract + instrumentSymbol: + type: string + description: Contract instrument symbol + example: "GEMI-FEDJAN26-DN25" + position: + type: string + description: Signed position held at settlement. Positive values represent a `yes` position; negative values represent a `no` position. + example: "125" + positionQuantity: + type: string + description: Absolute quantity held at settlement (unsigned) + example: "125" + outcome: + $ref: '#/components/schemas/Outcome' + payout: + type: string + description: Payout received from settlement. `0` when the position lost. + example: "125.00" + resolutionSide: + allOf: + - $ref: '#/components/schemas/Outcome' + description: The winning outcome of the contract + settledAt: + type: string + format: date-time + description: Settlement timestamp (ISO 8601) + contractMetadata: + $ref: '#/components/schemas/ContractMetadata' + costBasis: + type: string + nullable: true + description: Total amount spent to enter the position, net of any prior realized P&L from partial sells. Omitted when cost-basis data is not available. + example: "78.75" + realizedPnl: + type: string + nullable: true + description: Realized profit or loss recorded from sells prior to settlement. Omitted when not available. + example: "0" + netProfit: + type: string + nullable: true + description: Net profit for the position, computed as `payout - costBasis + realizedPnl`. Omitted when `costBasis` is not available. + example: "46.25" + + SettledPositionsResponse: + type: object + properties: + positions: + type: array + items: + $ref: '#/components/schemas/SettledPosition' + total: + type: integer + nullable: true + description: Total number of settled positions across all pages for the current filter set. + totalPayout: + type: string + description: Sum of `payout` across all settled positions in the filter set. Retained for binary back-compat with the legacy response shape; **field is absent (not `null`) on the unified backend** because computing a roll-up over the full filtered set would require a separate aggregate query (deferred until a partner asks). Play's default `OptionHandlers` omits absent `Option` fields rather than emitting `null`. + totalCostBasis: + type: string + description: Sum of `costBasis` across all settled positions in the filter set. Retained for binary back-compat; **field is absent (not `null`) on the unified backend** (see `totalPayout`). + totalNetProfit: + type: string + description: Sum of `netProfit` across all settled positions in the filter set. Retained for binary back-compat; **field is absent (not `null`) on the unified backend** (see `totalPayout`). + cashOuts: + type: array + description: | + Cash-outs (early sells before contract resolution) in the same account-scoped time window as the returned page's settled positions. Field is absent (not `null`) when `withCashOuts=true` is not passed on the request. `positions[]` pagination is unaffected — `limit`/`offset` continue to scope `positions[]` only. + items: + $ref: '#/components/schemas/CashedOutPosition' + totalCashOutProceeds: + type: string + description: Sum of `cashOuts[].proceeds` over the returned cash-outs. Field is absent (not `null`) when `withCashOuts=true` is not passed on the request. + example: "120.00" + totalCashOutCostBasis: + type: string + description: Sum of `cashOuts[].costBasis` over the returned cash-outs. Field is absent (not `null`) when `withCashOuts=true` is not passed on the request. + example: "100.00" + totalCashOutNetProfit: + type: string + description: Sum of `cashOuts[].netProfit` over the returned cash-outs. Field is absent (not `null`) when `withCashOuts=true` is not passed on the request. + example: "20.00" + + CashedOutPosition: + type: object + required: + - accountId + - instrumentId + - instrumentSymbol + - timestamp + - filledQuantity + - side + - proceeds + - costBasis + - netProfit + description: | + A qualifying cash-out (early sell before contract resolution) with cost-basis context. Exposed only via the `withCashOuts=true` sibling array on `POST /v1/prediction-markets/positions/settled`. Distinct from `SettledPosition` — cash-outs don't have a `payout` or `resolutionSide` since the contract hadn't resolved when the user sold. + properties: + accountId: + type: integer + format: int64 + description: Account that held the position. + example: 456 + instrumentId: + type: integer + format: int64 + description: Contract instrument ID. + example: 16789219 + instrumentSymbol: + type: string + description: Contract instrument symbol. + example: "GEMI-FEDJAN26-DN25" + timestamp: + type: string + format: date-time + description: Wall-clock timestamp when the cash-out order closed (ISO 8601). + example: "2026-05-15T14:30:00.000Z" + filledQuantity: + type: string + description: Quantity sold (cumulative filled quantity on the cash-out order). + example: "10" + side: + type: string + enum: [sell] + description: Always `sell` for cash-outs. + example: "sell" + proceeds: + type: string + description: Amount received from the sale in USD. For prediction sells, proceeds flow through `cash_balance` rather than `closed_orders.total_spend`, so the value is derived from position-balance snapshots before/after the fill. + example: "10.50" + costBasis: + type: string + description: Cost basis allocated proportionally to the filled quantity (`(costBasisSpend / costBasisPositionBalance) * filledQuantity`). + example: "10.00" + netProfit: + type: string + description: Realized P&L from this cash-out fill (`proceeds - costBasis`). Equals the ledger `realized_pl` delta on the position-balance row pair around the fill; falls back to `0` under transient market-data lag so a missing post-fill snapshot can't poison the page. + example: "0.50" + contractMetadata: + $ref: '#/components/schemas/ContractMetadata' + + ContractShareVolume: + type: object + properties: + symbol: + type: string + description: Contract instrument symbol + example: "GEMI-FED260318-CUT25" + totalQty: + type: string + description: Total taker volume across all participants (in shares) + example: "94625" + userAggressorQty: + type: string + nullable: true + description: The authenticated user's taker (aggressor) volume (in shares) + example: "1" + userRestingQty: + type: string + nullable: true + description: The authenticated user's maker (resting) volume (in shares) + example: "0" + + VolumeMetricsResponse: + type: object + properties: + eventTicker: + type: string + description: The event ticker + example: "FED260318" + contracts: + type: array + items: + $ref: '#/components/schemas/ContractShareVolume' + + PredictionMarketVolumeCategory: + type: object + required: + - categoryPath + - volume + properties: + categoryPath: + type: array + description: Display-name path from the top-level category to this category. It replaces recursive child nodes. + items: + type: string + example: ["Sports", "Football", "Pro Football"] + volume: + allOf: + - $ref: '#/components/schemas/PredictionMarketVolumeDecimal' + description: Total volume for this category, including all descendant categories. + + PredictionMarketHourlyVolumeCategory: + type: object + required: + - periodStart + - categoryPath + - volume + properties: + periodStart: + type: string + format: date-time + description: Inclusive UTC start of this hourly period. + example: "2026-07-20T00:00:00Z" + categoryPath: + type: array + description: Display-name path from the top-level category to this category. It replaces recursive child nodes. + items: + type: string + example: ["Sports", "Football", "Pro Football"] + volume: + allOf: + - $ref: '#/components/schemas/PredictionMarketVolumeDecimal' + description: Total volume for this category in this hour, including all descendant categories. + + PredictionMarketVolumeDecimal: + type: string + pattern: '^(?:0|[1-9][0-9]*)(?:\.[0-9]+)?$' + description: Non-negative decimal string. Preserve it as a string to avoid floating-point precision loss. + example: "143567.25" + + MakerRebateRateRule: + type: object + required: + - id + - rebate_multiplier_bps + - effective_from + properties: + id: + type: integer + format: int64 + description: Stable identifier for this rate rule. + example: 12 + rebate_multiplier_bps: + type: integer + format: int32 + description: Portion of the maker fee that is rebated, in basis points (10000 bps = 100%). + example: 5000 + effective_from: + type: string + format: date-time + nullable: true + description: ISO-8601 timestamp at which this rule becomes effective. Always present; in practice never `null`. + example: "2026-03-19T00:00:00Z" + category: + type: string + description: Market category this rule applies to. When absent, the rule applies to all categories. + example: "Crypto" + effective_to: + type: string + format: date-time + description: ISO-8601 timestamp after which this rule is superseded. Omitted when the rule is still current. + example: "2026-04-19T00:00:00Z" + + MakerRebateRatesResponse: + type: object + required: + - rate_rules + properties: + rate_rules: + type: array + items: + $ref: '#/components/schemas/MakerRebateRateRule' + + MakerRebatePayout: + type: object + required: + - id + - total_volume_usd + - total_rebate_usd + - total_fill_count + - status + - paid_at + - created_at + properties: + id: + type: integer + format: int64 + description: Stable payout identifier. + example: 9182 + total_volume_usd: + type: string + description: Total qualifying maker volume contributing to this payout, in USD. + example: "12450.00" + total_rebate_usd: + type: string + description: Total rebate paid, in USD. + example: "6.23" + total_fill_count: + type: integer + format: int32 + description: Number of qualifying maker fills that contributed to the payout. + example: 187 + status: + type: string + description: Payout status (e.g. `PENDING`, `PAID`). + example: "PAID" + paid_at: + type: string + format: date-time + nullable: true + description: ISO-8601 timestamp at which the rebate was credited. Always present; `null` for payouts that have not yet been paid. + example: "2026-05-20T21:00:00Z" + created_at: + type: string + format: date-time + nullable: true + description: ISO-8601 timestamp at which the payout row was created. Always present. + example: "2026-05-20T20:55:12Z" + + MakerRebatePayoutsResponse: + type: object + required: + - payouts + properties: + payouts: + type: array + items: + $ref: '#/components/schemas/MakerRebatePayout' + + MakerRebateLifetimeSummary: + type: object + required: + - total_earned_usd + - total_fill_count + - total_volume_usd + - payout_count + - first_payout_date + - last_payout_date + properties: + total_earned_usd: + type: string + description: Sum of `total_rebate_usd` across payouts in the window. + example: "152.40" + total_fill_count: + type: integer + format: int64 + description: Sum of qualifying maker fills across payouts in the window. + example: 4218 + total_volume_usd: + type: string + description: Sum of qualifying maker volume (USD) across payouts in the window. + example: "304800.00" + payout_count: + type: integer + format: int32 + description: Number of payouts in the window. Always present; `0` when no payouts exist in the window. + example: 27 + first_payout_date: + type: string + format: date + nullable: true + description: Date of the earliest payout in the window, or `null` if no payouts exist. + example: "2026-03-19" + last_payout_date: + type: string + format: date + nullable: true + description: Date of the most recent payout in the window, or `null` if no payouts exist. + example: "2026-05-20" + + LiquidityRewardsConfig: + type: object + required: + - enabled + properties: + max_spread_cents: + type: integer + format: int32 + description: Quotes wider than this spread score zero in the scoring algorithm. Only present when `enabled` is `true`. + example: 10 + min_payout_threshold_usd: + type: string + description: Daily reward amounts below this threshold are suppressed (sub-threshold accounts get no row at all). Only present when `enabled` is `true`. + example: "1.00" + enabled: + type: boolean + description: 'True when the program is fully configured upstream. When false, the response collapses to `{ "enabled": false }` only.' + example: true + + LiquidityRewardEvent: + type: object + required: + - event_ticker + - title + - category + - daily_pool_usd + - pool_source + - ends_at + - qualifying_maker_count + properties: + event_ticker: + type: string + description: Event ticker (e.g. `BTC2605202100`). + example: "BTC2605202100" + title: + type: string + description: Event title. + example: "BTC above $95,000?" + category: + type: string + description: Market category. + example: "Crypto" + daily_pool_usd: + type: string + description: Daily USD reward pool budgeted for this event. + example: "500.00" + pool_source: + type: string + enum: + - event_override + - category_default + - unspecified + description: Whether the pool came from a per-event override or the category default. + example: "event_override" + ends_at: + type: string + format: date-time + nullable: true + description: ISO-8601 timestamp at which the event ends and stops scoring. `null` when the underlying event has no end timestamp set. + example: "2026-05-20T21:00:00Z" + qualifying_maker_count: + type: integer + format: int32 + description: Number of accounts that met qualifying-maker criteria in the most recent snapshot window for this event. + example: 14 + icon_url: + type: string + description: Optional URL for the event icon. Omitted when not configured. + example: "https://example.com/btc.png" + + LiquidityRewardsEventsResponse: + type: object + required: + - events + - pagination + - last_score_date + properties: + events: + type: array + items: + $ref: '#/components/schemas/LiquidityRewardEvent' + pagination: + $ref: '#/components/schemas/Pagination' + last_score_date: + type: string + format: date + nullable: true + description: Most recent date for which scoring has been written. `null` when no scoring has run yet. + example: "2026-05-19" + + LiquidityEventScore: + type: object + required: + - event_id + - event_name + - category_name + - normalized_score + - snapshot_count + - total_snapshots + - event_reward_usd + properties: + event_id: + type: integer + format: int64 + description: Stable event identifier. + example: 1234567890 + event_name: + type: string + description: Event title. + example: "BTC above $95,000?" + category_name: + type: string + description: Market category. + example: "Crypto" + normalized_score: + type: string + description: This account's normalized score for the event on the scoring date (0-1 range as a decimal string). + example: "0.4521" + snapshot_count: + type: integer + format: int32 + description: Number of snapshots in which this account had a qualifying quote. + example: 1180 + total_snapshots: + type: integer + format: int32 + description: Total snapshots taken for the event on the scoring date. + example: 1440 + event_reward_usd: + type: string + description: Portion of the day's total reward attributed to this event. + example: "8.20" + + LiquidityDailySummary: + type: object + required: + - payout_date + - total_reward_usd + - payout_status + - paid_at + - events + properties: + payout_date: + type: string + format: date + description: Date the payout applies to (Eastern Time). + example: "2026-05-07" + total_reward_usd: + type: string + description: Total USD reward for the day across all events the account scored on. + example: "12.45" + payout_status: + type: string + description: Status of the day's payout (e.g. `PENDING`, `PAID`, `ZERO_AMOUNT`). + example: "PAID" + paid_at: + type: string + format: date-time + nullable: true + description: ISO-8601 timestamp the day's payout was credited. Always present; `null` if not yet paid. + example: "2026-05-08T21:00:00Z" + events: + type: array + description: Per-event score breakdown showing how the day's total was distributed. + items: + $ref: '#/components/schemas/LiquidityEventScore' + + LiquidityRewardsDailySummaryResponse: + type: object + required: + - daily_summaries + properties: + daily_summaries: + type: array + items: + $ref: '#/components/schemas/LiquidityDailySummary' + + LiquidityRewardsLifetimeSummary: + type: object + required: + - total_earned_usd + - payout_count + - first_payout_date + - last_payout_date + properties: + total_earned_usd: + type: string + description: Sum of `total_reward_usd` across daily payouts in the window. + example: "84.20" + payout_count: + type: integer + format: int32 + description: Number of daily payouts in the window. Always present; `0` when no payouts exist in the window. + example: 12 + first_payout_date: + type: string + format: date + nullable: true + description: Date of the earliest payout in the window, or `null` if no payouts exist. + example: "2026-05-08" + last_payout_date: + type: string + format: date + nullable: true + description: Date of the most recent payout in the window, or `null` if no payouts exist. + example: "2026-05-20" diff --git a/specs/openapi/rest.yaml b/specs/openapi/rest.yaml new file mode 100644 index 00000000..8feec896 --- /dev/null +++ b/specs/openapi/rest.yaml @@ -0,0 +1,10475 @@ +openapi: 3.0.3 +info: + title: REST API + description: | + The Gemini Crypto Exchange REST API allows programmatic access to trade cryptocurrencies + and manage your account on the Gemini Exchange platform. The API provides both public and + private endpoints for market data, order management, and account operations. + + version: "1.0.0" + contact: + name: Gemini Trading Support + email: trading@gemini.com +servers: + - url: https://api.gemini.com + description: Production server + - url: https://api.sandbox.gemini.com + description: Sandbox server for testing + +paths: + /v1/symbols: + get: + tags: + - Market Data + summary: List Symbols + operationId: listSymbols + description: This endpoint retrieves all available symbols for trading. + responses: + '200': + description: The full list of supported symbols. + content: + application/json: + schema: + type: array + items: + type: string + description: An array of supported [symbols](/market-data/symbols-and-minimums#all-supported-symbols). + example: ["aavegusd","aaveusd","aligusd","aliusd","ampgusd","ampusd","ankrgusd","ankrusd","apegusd","apeusd","api3gusd","api3usd","arbgusd","arbusd","atomgusd","atomusd","avaxgusd","avaxgusdperp","avaxusd","axsgusd","axsusd","batgusd","batusd","bchgusd","bchgusdperp","bchusd","bnbgusdperp","bomegusd","bomegusdperp","bomeusd","bonkgusd","bonkgusdperp","bonkusd","btceur","btcgbp","btcgusd","btcgusdperp","btcsgd","btcusd","btcusdt","chillguygusd","chillguyusd","chzgusd","chzusd","compgusd","compusd","crvgusd","crvusd","ctxgusd","ctxusd","cubegusd","cubeusd","daigusd","daiusd","dogebtc","dogeeth","dogegusd","dogegusdperp","dogeusd","dotgusd","dotgusdperp","dotusd","efilfil","elongusd","elonusd","ensgusd","ensusd","ethbtc","etheur","ethgbp","ethgusd","ethgusdperp","ethsgd","ethusd","ethusdt","fetgusd","fetusd","filgusd","filusd","flokigusd","flokigusdperp","flokiusd","ftmgusd","ftmusd","galagusd","galausd","gmtgusd","gmtusd","goatgusd","goatgusdperp","goatusd","grtgusd","grtusd","gusdgbp","gusdsgd","gusdusd","hntgusd","hntusd","hypegusdperp","imxgusd","imxusd","injgusd","injgusdperp","injusd","iotxgusd","iotxusd","ksl2gusdperp","kt5gusdperp","ldogusd","ldousd","linkbtc","linketh","linkgusd","linkgusdperp","linkusd","lptgusd","lptusd","lrcgusd","lrcusd","ltcbtc","ltceth","ltcgusd","ltcgusdperp","ltcusd","managusd","manausd","maskgusd","maskusd","maticgusd","maticusd","mewgusd","mewgusdperp","mewusd","mkrgusd","mkrusd","moodenggusd","moodenggusdperp","moodengusd","opgusd","opgusdperp","opusd","oxtgusd","oxtusd","paxggusd","paxgusd","pepegusd","pepegusdperp","pepeusd","pnutgusd","pnutgusdperp","pnutusd","polgusdperp","popcatgusd","popcatgusdperp","popcatusd","pythgusd","pythgusdperp","pythusd","qntgusd","qntusd","raregusd","rareusd","rengusd","renusd","rlusdusd","rndrgusd","rndrusd","samogusd","samousd","sandgusd","sandusd","shibgusd","shibgusdperp","shibusd","sklgusd","sklusd","solbtc","soleth","solgusd","solgusdperp","solusd","storjgusd","storjusd","sushigusd","sushiusd","trumpgusdperp","umagusd","umausd","unigusd","unigusdperp","uniusd","usdcusd","usdtgusd","usdtusd","wifgusd","wifgusdperp","wifusd","xrpgusd","xrpgusdperp","xrpusd","xtzgusd","xtzusd","yfigusd","yfiusd","zecgusd","zecusd","zrxgusd","zrxusd"] + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + + /v1/symbols/details/{symbol}: + get: + tags: + - Market Data + summary: Get Symbol Details + operationId: getSymbolDetails + description: This endpoint retrieves extra detail on supported symbols, such as minimum order size, tick size, quote increment and more. + parameters: + - $ref: '#/components/parameters/symbolParam' + responses: + '200': + description: Instrument responses examples + content: + application/json: + schema: + $ref: '#/components/schemas/SymbolDetails' + examples: + spot: + summary: Spot instrument + description: Spot instrument response + value: + symbol: BTCUSD + base_currency: BTC + quote_currency: USD + tick_size: 0.00000001 + quote_increment: 0.01 + min_order_size: "0.00001" + status: open + wrap_enabled: false + product_type: spot + contract_type: vanilla + contract_price_currency: USD + perpetual: + summary: Perpetual Swap instrument + description: Perpetual Swap instrument response + value: + symbol: BTCETHPERP + base_currency: BTC + quote_currency: ETH + tick_size: 0.0001 + quote_increment: 0.5 + min_order_size: "0.0001" + status: open + wrap_enabled: false + product_type: swap + contract_type: linear + contract_price_currency: GUSD + + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v2/networks/{network}/assets: + get: + tags: + - Market Data + summary: Get Assets for Network + operationId: getAssetsForNetwork + description: | + This endpoint retrieves the enabled assets (tokens) available on a specified blockchain network, filtered by your account's access permissions. + + This authenticated endpoint returns only the assets where your account has deposit and withdraw access enabled on the specified network. + + Use this endpoint to discover all tokens that support deposits and withdrawals on a particular blockchain network. + + The `assets` field in the response is always an array, sorted alphabetically, containing one or more enabled asset codes. + + ### Roles + The API key you use to access this endpoint must have the Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + - name: network + in: path + required: true + schema: + type: string + description: | + Blockchain network identifier (lowercase). Supported networks include: `ethereum`, `solana`, `bitcoin`, `optimism`, `arbitrum`, `base`, `monad`, `avalanche`, `litecoin`, `bitcoincash`, `dogecoin`, `zcash`, `filecoin`, `tezos`, `polkadot`, `cosmos`, `xrpl`, `linea`, and more. + example: ethereum + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + responses: + '200': + description: The response will be a JSON object containing the network name and its supported assets. + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkAssets' + examples: + multi-asset-network: + summary: Network with many assets (Ethereum) + value: + network: "ethereum" + assets: ["AAVE", "BAT", "DAI", "ETH", "LINK", "MATIC", "UNI", "USDC", "USDT", "WBTC"] + single-asset-network: + summary: Network with single asset (Bitcoin) + value: + network: "bitcoin" + assets: ["BTC"] + stablecoin-network: + summary: Network popular for stablecoins (Solana) + value: + network: "solana" + assets: ["BONK", "JTO", "JUP", "PYTH", "RAY", "RENDER", "SOL", "USDC"] + '400': + description: The supplied network is not supported or has no enabled assets. + content: + application/json: + schema: + type: object + properties: + errorMessage: + type: string + examples: + unsupported-network: + summary: Unsupported network + value: + errorMessage: "Supplied value 'foochain' is not a supported network. Please refer to the Supported Networks section at docs.gemini.com and correct your API request." + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v2/network/{token}: + get: + tags: + - Market Data + summary: Get Network + operationId: getTokenNetworkV2 + description: | + + + This endpoint retrieves the associated network(s) for a requested token, filtered by your account's access permissions. + + This authenticated endpoint returns only the networks where your account has both deposit and withdraw access enabled. This supports the multinetwork deposit and withdrawal flow. + + Many tokens are available on multiple blockchain networks. For example, USDC is available on Optimism, Solana, Base, Arbitrum, Avalanche, and Ethereum. Use this endpoint to discover which networks your account can deposit to and withdraw from for a given token. + + The `network` field in the response is always an array, which may contain one or more supported networks. + + ### Roles + The API key you use to access this endpoint must have the Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + - name: token + in: path + required: true + schema: + type: string + description: Token identifier. `BTC`, `ETH`, `USDC`, `SOL` etc. See [**symbols and minimums**](/market-data/symbols-and-minimums) + example: USDC + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + responses: + '200': + description: The response will be a JSON object containing the token and its available networks for the authenticated account. + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkToken' + examples: + single-network: + summary: Single network token (BTC) + value: + token: BTC + network: ["bitcoin"] + multi-network: + summary: Multi-network token (USDC) + value: + token: USDC + network: ["optimism", "solana", "base", "arbitrum", "avalanche", "ethereum"] + '400': + $ref: '#/components/responses/BadRequest' + '404': + description: Returned when the token is not supported or the account has no available networks for the requested token. + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: error + reason: + type: string + example: UnsupportedNetwork + message: + type: string + example: "UnsupportedNetwork: INVALIDTOKEN" + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/pubticker/{symbol}: + get: + tags: + - Market Data + summary: Get Ticker + operationId: getTicker + description: | + This endpoint retrieves information about recent trading activity for the symbol. + + + parameters: + - $ref: '#/components/parameters/symbolParam' + responses: + '200': + description: The current ticker for the symbol + content: + application/json: + schema: + $ref: '#/components/schemas/Ticker' + example: + bid: "977.59" + ask: "977.35" + last: "977.65" + volume: + BTC: "2210.505328803" + USD: "2135477.463379586263" + timestamp: 1483018200000 + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/feepromos: + get: + tags: + - Market Data + summary: List Fee Promos + operationId: listFeePromos + description: This endpoint retrieves symbols that currently have fee promos. + responses: + '200': + description: The response will be a JSON object + content: + application/json: + schema: + $ref: '#/components/schemas/FeePromos' + example: + symbols: ["BTCGUSDPERP"] + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/book/{symbol}: + get: + tags: + - Market Data + summary: Get Current Order Book + operationId: getCurrentOrderBook + x-zudoku-playground-enabled: false # Disable playground for this endpoint due to CORS configuration on server + description: | + This will return the current order book as two arrays (bids / asks). + + + parameters: + - $ref: '#/components/parameters/symbolParam' + - name: limit_bids + in: query + description: Limit the number of bid (offers to buy) price levels returned. Default is 50. May be 0 to return the full order book on this side. + required: false + schema: + type: number + minimum: 1 + - name: limit_asks + in: query + description: Limit the number of ask (offers to sell) price levels returned. Default is 50. May be 0 to return the full order book on this side. + required: false + schema: + type: number + minimum: 1 + responses: + '200': + description: The response will be two arrays. The bids and the asks are grouped by price, so each entry may represent multiple orders at that price. Each element of the array will be a JSON object. + content: + application/json: + schema: + $ref: '#/components/schemas/OrderBook' + example: + bids: [ + { + price: "3607.85", + amount: "6.643373", + timestamp: "1547147541" + } + ] + asks: [ + { + price: "3607.86", + amount: "14.68205084", + timestamp: "1547147541" + } + ] + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/trades/{symbol}: + get: + tags: + - Market Data + summary: List Trades + operationId: listTrades + x-zudoku-playground-enabled: false # Disable playground for this endpoint due to CORS configuration on server + description: | + + + This will return the trades that have executed since the specified timestamp. Timestamps are either seconds or milliseconds since the epoch (1970-01-01). See the [Data Types](/data-types) section about `timestamp` for information on this. + + Each request will show at most 500 records. + + If no `since` or `timestamp` is specified, then it will show the most recent trades; otherwise, it will show the most recent trades that occurred after that timestamp. + parameters: + - $ref: '#/components/parameters/symbolParam' + - name: timestamp + in: query + description: | + Only return trades after this timestamp. See [**Timestamps**](/rest/~schemas#timestamp-type) for more information. If not present, will show the most recent trades. For backwards compatibility, you may also use the alias `since`. With timestamp, there is a 90-day hard limit. + required: false + schema: + $ref: '#/components/schemas/TimestampType' + description: Timestamp in milliseconds + - name: since_tid + in: query + description: | + Only retuns trades that executed after this tid. since_tid trumps timestamp parameter which has no effect if provided too. You may set since_tid to zero to get the earliest available trade history data. + required: false + schema: + type: number + - name: limit_trades + in: query + description: | + The maximum number of trades to return. The default is 50. + required: false + schema: + type: number + minimum: 0 + default: 50 + - name: include_breaks + in: query + description: | + Whether to display broken trades. False by default. Can be `1` or `true` to activate + required: false + schema: + type: boolean + default: false + responses: + '200': + description: The response will be an array of JSON objects, sorted by timestamp, with the newest trade shown first. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Trade' + example: + timestamp: 1547146811 + timestampms: 1547146811357 + tid: 5335307668 + price: "3610.85" + amount: "0.27413495" + exchange: "gemini" + type: "buy" + broken: true + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/pricefeed: + get: + tags: + - Market Data + summary: List Prices + operationId: listPrices + responses: + '200': + description: Response is a list of objects, one for each pair. + content: + application/json: + schema: + $ref: '#/components/schemas/PriceFeedResponse' + example: [ + { + "pair":"BTCUSD", + "price":"9500.00", + "percentChange24h": "5.23" + }, + { + "pair":"ETHUSD", + "price":"257.54", + "percentChange24h": "4.85" + }, + { + "pair":"BCHUSD", + "price":"450.10", + "percentChange24h": "-2.91" + }, + { + "pair":"LTCUSD", + "price":"79.50", + "percentChange24h": "7.63" + } + ] + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/fundingamount/{symbol}: + get: + tags: + - Market Data + summary: Get Funding Amount + operationId: getFundingAmount + parameters: + - name: symbol + in: path + required: true + schema: + type: string + description: | + Trading pair symbol

+ + `BTCGUSDPERP`, etc. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols). + example: BTCGUSDPERP + responses: + '200': + description: The response will be an object + content: + application/json: + schema: + $ref: '#/components/schemas/FundingAmountResponse' + example: { + symbol: BTCGUSDPERP, + fundingDateTime: "2025-04-22T18:00:00.000Z", + fundingTimestampMilliSecs: 1745344800000, + nextFundingTimestamp: 1745348400000, + fundingAmount: -1.50991, + estimatedFundingAmount: -2.10595 + } + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/nextfundingtimestamp/{symbol}: + get: + tags: + - Market Data + summary: Get Next Funding Timestamp + operationId: getNextFundingTimestamp + parameters: + - name: symbol + in: path + required: true + schema: + type: string + description: | + Trading pair symbol

+ + `BTCGUSDPERP`, etc. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols). + example: BTCGUSDPERP + responses: + '200': + description: The response will be an integer timestamp in milliseconds. + content: + application/json: + schema: + type: integer + format: int64 + example: 1745348400000 + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/fundingamountreport/records.xlsx: + get: + tags: + - Market Data + summary: Get Funding Amount Report File + operationId: getFundingAmountReportFile + description: | + ### Examples + - `symbol=BTCGUSDPERP&fromDate=2024-04-10&toDate=2024-04-25&numRows=1000`
+ Compare and obtain the minimum records between (2024-04-10 to 2024-04-25) and 1000. If (2024-04-10 to 2024-04-25) contains 360 records. Then fetch the minimum between 360 and 1000 records only. + + - `symbol=BTCGUSDPERP&numRows=2024-04-10&toDate=2024-04-25`
+ If (2024-04-10 to 2024-04-25) contains 360 records. Then fetch 360 records only. + + - `symbol=BTCGUSDPERP&numRows=1000`
+ Fetch maximum 1000 records starting from Now to a historical date + + - `symbol=BTCGUSDPERP`
+ Fetch maximum 8760 records starting from Now to a historical date + + parameters: + - name: symbol + in: query + description: | + Trading pair symbol

+ + `BTCGUSDPERP`, etc. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols). + required: true + schema: + type: string + - name: fromDate + in: query + description: Mandatory if `toDate` is specified, else optional. If empty, will only fetch records by numRows value. + required: false + schema: + type: string + format: date + - name: toDate + in: query + description: Mandatory if `fromDate` is specified, else optional. If empty, will only fetch records by numRows value. + required: false + schema: + type: string + format: date + - name: numRows + in: query + description: If empty, default value '8760' + required: false + schema: + type: integer + + responses: + '200': + description: The response will be an excel / csv file. filename=FundingAmount_{SYMBOL}.{xlsx,csv} + headers: + Content-Disposition: + schema: + type: string + example: attachment; filename=FundingAmount_{SYMBOL}.{xlsx,csv} + content: + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: + schema: + type: string + format: binary + text/csv: + schema: + type: string + format: binary + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/order/new: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: Create New Order + operationId: createNewOrder + description: | + If you wish orders to be automatically cancelled when your session ends, see the [require heartbeat](/authentication/api-key#require-heartbeat) section, or manually send the [cancel all session orders](/rest/orders#cancel-all-session-orders) message. + + + + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See Roles for more information. + + The OAuth scope must have `orders:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + + ### Margin Orders + Set `margin_order: true` to place an order using borrowed funds on a margin-enabled account. This allows you to trade with leverage beyond your available balance. + + **Important**: Margin trading amplifies both gains and losses. Monitor your account using the [Margin Account Summary](/rest/margin-trading#get-margin-account-summary) endpoint and preview order impacts with [Order Preview](/rest/margin-trading#preview-margin-order-impact) before placing margin orders. + + ### Stop-Limit Orders + A Stop-Limit order is an order type that allows for order placement when a price reaches a specified level. Stop-Limit orders take in both a `price` and and a `stop_price` as parameters. The `stop_price` is the price that triggers the order to be placed on the continous live order book at the `price`. For buy orders, the `stop_price` must be below the `price` while sell orders require the `stop_price` to be greater than the `price`. + + + ### What about market orders? + The API doesn't directly support market orders because they provide you with no price protection. + + Instead, use the “immediate-or-cancel” order execution option, coupled with an aggressive limit price (i.e. very high for a buy order or very low for a sell order), to achieve the same result. + + ### Order execution options + Note that `options` is an array. If you omit `options` or provide an empty array, your order will be a standard limit order - it will immediately fill against any open orders at an equal or better price, then the remainder of the order will be posted to the order book. + + If you specify more than one option (or an unsupported option) in the `options` array, the exchange will reject your order. + + No `options` can be applied to stop-limit orders at this time. + + The available limit order options are: + + | Option | Description | + |--------|-------------| + | `"maker-or-cancel"` | This order will only add liquidity to the order book.

If any part of the order could be filled immediately, the whole order will instead be canceled before any execution occurs.

If that happens, the response back from the API will indicate that the order has already been canceled (`"is_cancelled": true` in JSON).

*Note: some other exchanges call this option "post-only".* | + | `"immediate-or-cancel"` | This order will only remove liquidity from the order book.

It will fill whatever part of the order it can immediately, then cancel any remaining amount so that no part of the order is added to the order book.

If the order doesn't fully fill immediately, the response back from the API will indicate that the order has already been canceled (`"is_cancelled": true` in JSON). | + | `"fill-or-kill"` | This order will only remove liquidity from the order book.

It will fill the entire order immediately or cancel.

If the order doesn't fully fill immediately, the response back from the API will indicate that the order has already been canceled (`"is_cancelled": true` in JSON). | + + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NewOrderRequest' + examples: + limitOrder: + summary: Limit Order + description: JSON limit order payload + value: + request: /v1/order/new + nonce: + client_order_id: "470135" + symbol: BTCUSD + amount: "5" + price: "3633.00" + side: buy + type: exchange limit + stopLimitOrder: + summary: Stop-Limit Order + description: JSON stop-limit order payload + value: + request: /v1/order/new + nonce: + client_order_id: "921841" + symbol: BTCUSD + amount: "0.1" + price: "10500" + side: buy + type: exchange stop limit + stop_price: "10000" + marginOrder: + summary: Margin Order + description: JSON margin order payload using borrowed funds + value: + request: /v1/order/new + nonce: + client_order_id: "384729" + symbol: ETHUSD + amount: "2.5" + price: "3200.00" + side: buy + type: exchange limit + margin_order: true + responses: + '200': + description: Response will be the fields included in Order Status + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/LimitOrderResponse' + - $ref: '#/components/schemas/StopLimitOrderResponse' + examples: + limitOrder: + summary: Limit Order + description: JSON limit order response + value: + order_id: "106817811" + id: "106817811" + symbol: BTCUSD + exchange: gemini + avg_execution_price: "3632.8508430064554" + side: buy + type: exchange limit + timestamp: "1547220404" + timestampms: 1547220404836 + is_live: true + is_cancelled: false + is_hidden: false + was_forced: false + executed_amount: "3.7567928949" + remaining_amount: "1.2432071051" + client_order_id: "20190110-4738721" + options: [] + price: "3633.00" + original_amount: "5" + stopLimitOrder: + summary: Stop-Limit Order + description: JSON stop-limit order response + value: + order_id: "7419662" + id: "7419662" + symbol: BTCUSD + exchange: gemini + avg_execution_price: "0.00" + side: buy + type: stop-limit + timestamp: "1572378649" + timestampms: 1572378649018 + is_live: true + is_cancelled: false + is_hidden: false + was_forced: false + executed_amount: "0" + options: [] + stop_price: "10400.00" + price: "10500.00" + original_amount: "0.01" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/order/cancel: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: Cancel Order + operationId: cancelOrder + description: | + This will cancel an order. If the order is already canceled, the message will succeed but have no effect. + + + + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles) for more information. + + The OAuth scope must have `orders:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + ### All Cancellation Reasons + Under unique circumstances, orders may be automatically cancelled by the exchange. These scenarios are detailed in the table below: + + | Cancel Reason | Description | + |---------------|-------------| + | `MakerOrCancelWouldTake` | Occurs when the "maker-or-cancel" execution option is included in the order request and any part of the requested order could be filled immediately. | + | `ExceedsPriceLimits` | Occurs when there is not sufficient liquidity on the order book to support the entered trade. Orders will be automatically cancelled when liquidity conditions are such that the order would move price +/- 5%. | + | `SelfCrossPrevented` | Occurs when a user enters a bid that is higher than that user's lowest open ask or enters an ask that is lower than their highest open bid on the same pair. | + | `ImmediateOrCancelWouldPost` | Occurs when the "immediate-or-cancel" execution option is included in the order request and the requested order cannot be fully filled immediately. This type of cancellation will only cancel the unfulfilled part of any impacted order. | + | `FillOrKillWouldNotFill` | Occurs when the "fill-or-kill" execution option is included in the new order request and the entire order cannot be filled immediately.

Unlike "immediate-or-cancel" orders, this execution option will result in the entire order being cancelled rather than just the unfulfilled portion. | + | `Requested` | Cancelled via user request to /v1/order/cancel endpoint. | + | `MarketClosed` | Occurs when an order is placed for a trading pair that is currently closed. | + | `TradingClosed` | Occurs when an order is placed while the exchange is closed for trading. | + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CancelOrderRequest' + examples: + cancelOrder: + summary: Cancel Order Example + description: JSON payload to cancel an order using its order_id + value: + request: /v1/order/cancel + nonce: + order_id: 106817811 + responses: + '200': + description: Response will be the fields included in Order Status. If the order was already canceled, then the request will have no effect and the status will be returned. Note the *is_cancelled* node will have a value of 'true' + content: + application/json: + schema: + $ref: '#/components/schemas/CancelOrderResponse' + examples: + cancelledOrder: + summary: Cancelled Order + description: JSON response for a cancelled order + value: + order_id: "106817811" + id: "106817811" + symbol: "btcusd" + exchange: "gemini" + avg_execution_price: "3632.85101103" + side: "buy" + type: "exchange limit" + timestamp: "1495742383" + timestampms: 1495742383345 + is_live: false + is_cancelled: true + is_hidden: false + was_forced: false + executed_amount: "3.7610296649" + remaining_amount: "1.2389703351" + reason: "Requested" + options: [] + price: "2960.00" + original_amount: "5" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/order/cancel/all: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: Cancel All Active Orders + operationId: cancelAllActiveOrders + description: | + This will cancel all outstanding orders created by all [sessions](/authentication/api-key#sessions) owned by this account, including interactive orders placed through the UI. + + + + Typically [Cancel All Session Orders](/rest/orders#cancel-all-session-orders) is preferable, so that only orders related to the current connected session are cancelled. + + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `orders:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CancelAllOrdersRequest' + examples: + cancelAllOrders: + summary: Cancel All Orders + description: JSON payload to cancel all orders + value: + request: /v1/order/cancel/all + nonce: + responses: + '200': + description: JSON response + content: + application/json: + schema: + $ref: '#/components/schemas/CancelAllResult' + example: + result: "ok" + details: { + cancelRejects: [], + cancelledOrders: [ + 330429106, + 330429079, + 330429082 + ] + } + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/order/cancel/session: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: Cancel All Session Orders + operationId: cancelAllSessionOrders + description: | + This will cancel all orders opened by this [session](/authentication/api-key#sessions). + + This will have the same effect as [heartbeat](/authentication/api-key#require-heartbeat) expiration if "Require Heartbeat" is selected for the session. + + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `orders:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CancelAllOrdersBySessionRequest' + examples: + cancelAllSessionOrders: + summary: Cancel All Session Orders + description: JSON payload to cancel all orders opened by this session + value: + request: /v1/order/cancel/session + nonce: + responses: + '200': + description: JSON response + content: + application/json: + schema: + $ref: '#/components/schemas/CancelAllResult' + example: + result: "ok" + details: { + cancelRejects: [330429345], + cancelledOrders: [] + } + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/order/status: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: Get Order Status + operationId: getOrderStatus + description: | + + + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `orders:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/OrderStatusRequest' + examples: + orderStatusRequest: + value: + request: /v1/order/status + nonce: + order_id: 123456789012345 + include_trades: true + responses: + '200': + description: The order status + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + examples: + limitBuyResponse: + summary: Limit Buy Response + description: JSON response for limit buy + value: + order_id: "123456789012345" + id: "123456789012345" + symbol: "btcusd" + exchange: "gemini" + avg_execution_price: "400.00" + side: "buy" + type: "exchange limit" + timestamp: "1494870642" + timestampms: 1494870642156 + is_live: false + is_cancelled: false + is_hidden: false + was_forced: false + executed_amount: "3" + remaining_amount: "0" + options: [] + price: "400.00" + original_amount: "3" + includeTradesResponse: + summary: Include Trades Response + description: JSON response for market buy with include_trades as True + value: + avg_execution_price: "22728.94" + exchange: "gemini" + executed_amount: "0.0219983861" + id: "17379712927" + is_cancelled: false + is_hidden: false + is_live: false + options: [] + order_id: "17379712927" + remaining_amount: "0" + side: "buy" + symbol: "btcusd" + timestamp: "1608229172" + timestampms: 1608229172627 + trades: [ + { + aggressor: true, + amount: "0.0219983861", + exchange: gemini, + fee_amount: "0.00", + fee_currency: USD, + order_id: "17379712927", + price: "22728.94", + tid: 17379712930, + timestamp: 1608229172, + timestampms: 1608229172627, + type: Buy + } + ] + type: "market buy" + was_forced: false + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/orders: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: List Active Orders + operationId: listActiveOrders + description: | + + + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `orders:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The API endpoint path + example: /v1/orders + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + example: primary + examples: + basic: + summary: Basic Request + description: Basic request to get active orders + value: + request: /v1/orders + nonce: + withAccount: + summary: With Account Parameter + description: Request with account parameter for Master API keys + value: + request: /v1/orders + nonce: + account: primary + responses: + '200': + description: The active orders + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Order' + examples: + multipleOrders: + summary: Multiple Active Orders + description: Response with multiple active orders + value: + - order_id: "107421210" + id: "107421210" + symbol: "ethusd" + exchange: "gemini" + avg_execution_price: "0.00" + side: "sell" + type: "exchange limit" + timestamp: "1547241628" + timestampms: 1547241628042 + is_live: true + is_cancelled: false + is_hidden: false + was_forced: false + executed_amount: "0" + remaining_amount: "1" + options: [] + price: "125.51" + original_amount: "1" + - order_id: "107421205" + id: "107421205" + symbol: "ethusd" + exchange: "gemini" + avg_execution_price: "125.41" + side: "buy" + type: "exchange limit" + timestamp: "1547241626" + timestampms: 1547241626991 + is_live: true + is_cancelled: false + is_hidden: false + was_forced: false + executed_amount: "0.029147" + remaining_amount: "0.970853" + options: [] + price: "125.42" + original_amount: "1" + emptyOrders: + summary: No Active Orders + description: Response when there are no active orders + value: [] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/orders/history: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: List Past Orders + operationId: listPastOrders + description: | + This API retrieves (closed) orders history for an account. + + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `history:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + + ### How to retrieve your order history + + To retrieve your full order history walking backwards, + + 1. Initial request: `POST` to https://api.gemini.com/v1/orders/history with a JSON payload including a `timestamp` key with value `0` and a `limit_orders` key with value `500` + 2. When you receive the list of orders, it will be sorted by `timestamp` descending - so the first element in the list will have the highest `timestamp` value. For this example, say that value is `X`. + 3. Create a second `POST` request with a JSON payload including a `timestamp` key with value `X+1` and a `limit_orders` key with value `500`. + 4. Take the first element of the list returned with highest `timestamp` value `Y` and create a third `POST` request with a JSON payload including a `timestamp` key with value `Y+1` and a `limit_orders` key with value `500`. + 5. Continue creating `POST` requests and retrieving orders until an empty list is returned. + + ### Break Types + + In the rare event that a trade has been reversed (broken), the trade that is broken will have this flag set. The field will contain one of these values + + |Value|Description| + |--- |--- | + |manual|The trade was reversed manually. This means that all fees, proceeds, and debits associated with the trade have been credited or debited to the account seperately. That means that this reported trade must be included for order for the account balance to be correct.| + |full|The trade was fully broken. The reported trade should not be accounted for. It will be as though the transfer of fund associated with the trade had simply not happened.| + + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The API endpoint `/v1/orders/history` + nonce: + $ref: '#/components/schemas/Nonce' + symbol: + type: string + description: "The symbol to retrieve orders for" + limit_orders: + type: integer + description: "The maximum number of orders to return. Default is 50, max is 500." + default: 50 + timestamp: + title: '#/components/schemas/TimestampType' + description: "In iso datetime with timezone format from that date you will get order history" + allOf: + - $ref: '#/components/schemas/TimestampType' + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group." + examples: + basic: + summary: Basic Request + description: Basic request to get order history + value: + request: /v1/orders/history + nonce: + limit_orders: 50 + withSymbolAndTimestamp: + summary: With Symbol and Timestamp + description: Request with symbol and timestamp filters + value: + request: /v1/orders/history + nonce: + symbol: btcusd + timestamp: 1591084414000 + limit_orders: 50 + withAccount: + summary: With Account Parameter + description: Request with account parameter for Master API keys + value: + request: /v1/orders/history + nonce: + account: primary + limit_orders: 100 + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Order' + examples: + cancelledOrder: + summary: Cancelled Order + description: Response with a cancelled order + value: + - order_id: "73751560172006688" + id: "73751560172006688" + symbol: "ethgusd" + exchange: "gemini" + avg_execution_price: "0.00" + side: "buy" + type: "exchange limit" + timestamp: "1695629298" + timestampms: 1695629298505 + is_live: false + is_cancelled: true + is_hidden: false + was_forced: false + executed_amount: "0" + client_order_id: "fb5321b0-2114-47fd-8cca-531a66d7feaf" + options: [] + price: "420.00" + original_amount: "0.69" + remaining_amount: "0.69" + trades: [] + completedOrder: + summary: Completed Order + description: Response with a completed order + value: + - order_id: "107421205" + id: "107421205" + symbol: "btcusd" + exchange: "gemini" + avg_execution_price: "3633.00" + side: "buy" + type: "exchange limit" + timestamp: "1547241626" + timestampms: 1547241626991 + is_live: false + is_cancelled: false + is_hidden: false + was_forced: false + executed_amount: "5" + remaining_amount: "0" + options: [] + price: "3633.00" + original_amount: "5" + trades: [ + { + price: "3633.00", + amount: "5", + timestamp: 1547241627, + timestampms: 1547241627000, + type: "Buy", + aggressor: true, + fee_currency: "USD", + fee_amount: "9.0825", + tid: 106921823, + order_id: "107421205", + exchange: "gemini" + } + ] + emptyHistory: + summary: Empty History + description: Response when there are no orders in history + value: [] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/mytrades: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: List Past Trades + operationId: listPastTrades + description: | + + + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `history:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + ### How to retrieve your trade history + + To retrieve your full trade history walking backwards, + + 1. Initial request: `POST` to https://api.gemini.com/v1/mytrades with a JSON payload including a `timestamp` key with value 0 and a `limit_trades` key with value `500` + 2. When you receive the list of trades, it will be sorted by `timestamp` descending - so the first element in the list will have the highest `timestamp` value. For this example, say that value is `X`. + 3. Create a second `POST` request with a JSON payload including a `timestamp` key with value `X+1` and a `limit_trades` key with value `500`. + 4. Take the first element of the list returned with highest `timestamp` value `Y` and create a third `POST` request with a JSON payload including a `timestamp` key with value `Y+1` and a `limit_trades` key with value `500`. + 5. Continue creating `POST` requests and retrieving trades until an empty list is returned. + + ### Break Types + + In the rare event that a trade has been reversed (broken), the trade that is broken will have this flag set. The field will contain one of these values + + |Value|Description| + |--- |--- | + |manual|The trade was reversed manually. This means that all fees, proceeds, and debits associated with the trade have been credited or debited to the account seperately. That means that this reported trade must be included for order for the account balance to be correct.| + |full|The trade was fully broken. The reported trade should not be accounted for. It will be as though the transfer of fund associated with the trade had simply not happened.| + + + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/MyTradesRequest' + examples: + basic: + summary: Basic Request + description: Basic request to get past trades for a symbol + value: + request: /v1/mytrades + nonce: + symbol: btcusd + withLimitAndTimestamp: + summary: With Limit and Timestamp + description: Request with limit and timestamp parameters + value: + request: /v1/mytrades + nonce: + symbol: btcusd + limit_trades: 100 + timestamp: 1591084414000 + withAccount: + summary: With Account Parameter + description: Request with account parameter for Master API keys + value: + request: /v1/mytrades + nonce: + symbol: btcusd + account: primary + responses: + '200': + description: The past trades + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/MyTrade' + examples: + multipleTrades: + summary: Multiple Trades + description: Response with multiple trades + value: + - price: "3648.09" + amount: "0.0027343246" + timestamp: 1547232911 + timestampms: 1547232911021 + type: "Buy" + aggressor: true + fee_currency: "USD" + fee_amount: "0.024937655575035" + tid: 107317526 + order_id: "107317524" + exchange: "gemini" + is_clearing_fill: false + symbol: "BTCUSD" + - price: "3633.00" + amount: "0.00423677" + timestamp: 1547220640 + timestampms: 1547220640195 + type: "Buy" + aggressor: false + fee_currency: "USD" + fee_amount: "0.038480463525" + tid: 106921823 + order_id: "106817811" + exchange: "gemini" + is_clearing_fill: false + symbol: "BTCUSD" + withClientOrderId: + summary: Trade with Client Order ID + description: Response with a trade that includes client_order_id + value: + - price: "42000.00" + amount: "0.5" + timestamp: 1616492376 + timestampms: 1616492376594 + type: "Sell" + aggressor: true + fee_currency: "USD" + fee_amount: "52.50" + tid: 123456789 + order_id: "123456789" + client_order_id: "my-custom-id-12345" + exchange: "gemini" + is_clearing_fill: false + symbol: "BTCUSD" + emptyTrades: + summary: No Trades + description: Response when there are no trades matching the criteria + value: [] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/tradevolume: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: Get Trading Volume + operationId: getTradingVolume + description: | + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `history:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The API endpoint path + example: /v1/tradevolume + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + example: primary + examples: + basic: + summary: Basic Request + description: Basic request to get trade volume + value: + request: /v1/tradevolume + nonce: + withAccount: + summary: With Account Parameter + description: Request with account parameter for Master API keys + value: + request: /v1/tradevolume + nonce: + account: primary + responses: + '200': + description: The trade volume + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TradeVolume' + examples: + multipleSymbols: + summary: Multiple Symbols + description: Response with trade volume for multiple symbols + value: + - - symbol: btcusd + base_currency: BTC + notional_currency: USD + data_date: "2019-01-10" + total_volume_base: 8.06021756 + maker_buy_sell_ratio: 1 + buy_maker_base: 6.06021756 + buy_maker_notional: 23461.3515203844 + buy_maker_count: 34 + sell_maker_base: 0 + sell_maker_notional: 0 + sell_maker_count: 0 + buy_taker_base: 0 + buy_taker_notional: 0 + buy_taker_count: 0 + sell_taker_base: 2 + sell_taker_notional: 7935.66 + sell_taker_count: 2 + - symbol: ltcusd + base_currency: LTC + notional_currency: USD + data_date: "2019-01-11" + total_volume_base: 3 + maker_buy_sell_ratio: 0 + buy_maker_base: 0 + buy_maker_notional: 0 + buy_maker_count: 0 + sell_maker_base: 0 + sell_maker_notional: 0 + sell_maker_count: 0 + buy_taker_base: 3 + buy_taker_notional: 98.22 + buy_taker_count: 3 + sell_taker_base: 0 + sell_taker_notional: 0 + sell_taker_count: 0 + singleSymbol: + summary: Single Symbol + description: Response with trade volume for a single symbol + value: + - - symbol: ethusd + base_currency: ETH + notional_currency: USD + data_date: "2019-01-10" + total_volume_base: 25.5 + maker_buy_sell_ratio: 0.75 + buy_maker_base: 15.5 + buy_maker_notional: 3875.00 + buy_maker_count: 12 + sell_maker_base: 5.0 + sell_maker_notional: 1250.00 + sell_maker_count: 4 + buy_taker_base: 2.5 + buy_taker_notional: 625.00 + buy_taker_count: 2 + sell_taker_base: 2.5 + sell_taker_notional: 625.00 + sell_taker_count: 2 + emptyVolume: + summary: No Trade Volume + description: Response when there is no trade volume + value: [[]] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/balances: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Get Available Balances + operationId: getAvailableBalances + description: | + + + This will show the available balances in the supported currencies + + + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `balances:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - account + properties: + request: + type: string + description: The API endpoint path + example: /v1/balances + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + type: string + example: primary + showPendingBalances: + description: | + Whether to include pending balances such as in-flight crypto deposits or withdrawals in the balances response. + + > **Note:** Setting this field to `true` will result in slower response times due to additional database lookups required to retrieve pending balance information. + default: false + type: boolean + example: false + example: + request: /v1/balances + nonce: + account: primary + showPendingBalances: false + responses: + '200': + description: The account balances + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Balance' + examples: + multipleBalances: + summary: Multiple Balances + description: Response with multiple currency balances (showPendingBalances = false) + value: + - type: "exchange" + currency: "BTC" + amount: "5.0" + available: "4.5" + availableForWithdrawal: "4.5" + _timestamp: "2024-03-16T00:00:00.000000Z" + - type: "exchange" + currency: "USD" + amount: "15000.00" + available: "5000.00" + availableForWithdrawal: "5000.00" + _timestamp: "2024-03-16T00:00:00.000000Z" + - type: "exchange" + currency: "ETH" + amount: "10.0" + available: "10.0" + availableForWithdrawal: "10.0" + _timestamp: "2024-03-16T00:00:00.000000Z" + emptyBalances: + summary: Empty Balances + description: Response when there are no balances + value: [] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/notionalvolume: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: Get Notional Trading Volume + operationId: getNotionalTradingVolume + description: | + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `history:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The API endpoint path + example: /v1/notionalvolume + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + example: primary + symbol: + type: string + description: "Optional. The symbol to get fee promotions or specific fee schedule rates for." + example: btcusd + examples: + basic: + summary: Basic Request + description: Basic request to get notional volume + value: + request: /v1/notionalvolume + nonce: + withSymbol: + summary: With Symbol Parameter + description: Request with symbol parameter for fee promotions + value: + request: /v1/notionalvolume + nonce: + symbol: btcusd + withAccount: + summary: With Account Parameter + description: Request with account parameter for Master API keys + value: + request: /v1/notionalvolume + nonce: + account: primary + responses: + '200': + description: The notional volume + content: + application/json: + schema: + $ref: '#/components/schemas/NotionalVolume' + examples: + standardResponse: + summary: Standard Response + description: Response with notional volume and fee information + value: + web_maker_fee_bps: 25 + web_taker_fee_bps: 35 + web_auction_fee_bps: 25 + api_maker_fee_bps: 10 + api_taker_fee_bps: 35 + api_auction_fee_bps: 20 + fix_maker_fee_bps: 10 + fix_taker_fee_bps: 35 + fix_auction_fee_bps: 20 + notional_30d_volume: 150.00 + last_updated_ms: 1551371446000 + date: "2019-02-28" + notional_1d_volume: [ + { + date: "2019-02-22", + notional_volume: 75.00 + }, + { + date: "2019-02-14", + notional_volume: 75.00 + } + ] + withFeeTier: + summary: With Fee Tier + description: Response including fee tier information + value: + web_maker_fee_bps: 25 + web_taker_fee_bps: 35 + web_auction_fee_bps: 25 + api_maker_fee_bps: 0 + api_taker_fee_bps: 10 + api_auction_fee_bps: 10 + fix_maker_fee_bps: 0 + fix_taker_fee_bps: 10 + fix_auction_fee_bps: 10 + notional_30d_volume: 15000000.00 + api_notional_30d_volume: 12500000.00 + last_updated_ms: 1551371446000 + date: "2019-02-28" + fee_tier: { + tier: "0bps", + api_maker_fee_bps: 0, + api_taker_fee_bps: 10 + } + notional_1d_volume: [ + { + date: "2019-02-28", + notional_volume: 500000.00 + }, + { + date: "2019-02-27", + notional_volume: 750000.00 + } + ] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/margin/account: + post: + x-zudoku-playground-enabled: false + tags: + - Margin Trading + summary: Get Margin Account Summary + operationId: getMarginAccount + description: | + Retrieves comprehensive margin account information including collateral, leverage, buying/selling power, and liquidation risk. + + This endpoint provides real-time margin statistics for spot margin trading accounts, helping you monitor your account health and manage risk. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `balances:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + ### Account Type + This endpoint is only available for margin trading accounts. Standard exchange accounts will receive an error. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/margin/account" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group." + example: + request: "/v1/margin/account" + nonce: + + responses: + '200': + description: Margin account summary with risk statistics + content: + application/json: + schema: + $ref: '#/components/schemas/MarginAccountSummary' + example: + marginAssetValue: + currency: "USD" + value: "10000.00" + availableCollateral: + currency: "USD" + value: "8500.00" + notionalValue: + currency: "USD" + value: "15000.00" + totalBorrowed: + currency: "USD" + value: "5000.00" + leverage: "1.5" + buyingPower: + currency: "USD" + value: "8500.00" + sellingPower: + currency: "USD" + value: "8500.00" + liquidationRisk: + lossPercentage: "0.1550" + liquidationPrice: + currency: "USD" + value: "50000.00" + interestRate: + rate: "0.00001141552511" + interval: "hour" + reservedBuyOrders: + currency: "USD" + value: "1000.00" + reservedSellOrders: + currency: "USD" + value: "500.00" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/margin/rates: + post: + x-zudoku-playground-enabled: false + tags: + - Margin Trading + summary: Get Margin Interest Rates + operationId: getMarginRates + description: | + Retrieves current margin interest rates for all borrowable assets. + + Returns hourly, daily, and annual borrow rates for each currency that can be borrowed on margin. Interest is charged on borrowed amounts at the hourly rate and compounds over time. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `balances:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + ### Account Type + This endpoint is only available for margin trading accounts. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/margin/rates" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group." + example: + request: "/v1/margin/rates" + nonce: + + responses: + '200': + description: Current margin interest rates for all borrowable assets + content: + application/json: + schema: + $ref: '#/components/schemas/MarginRatesResponse' + example: + rates: + - currency: "BTC" + borrowRate: "0.00001141552511" + borrowRateDaily: "0.00027397260264" + borrowRateAnnual: "0.1" + lastUpdated: 1700000000000 + - currency: "ETH" + borrowRate: "0.00001141552511" + borrowRateDaily: "0.00027397260264" + borrowRateAnnual: "0.1" + lastUpdated: 1700000000000 + - currency: "USD" + borrowRate: "0.00000913242009" + borrowRateDaily: "0.00021917808216" + borrowRateAnnual: "0.08" + lastUpdated: 1700000000000 + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/margin/order/preview: + post: + x-zudoku-playground-enabled: false + tags: + - Margin Trading + summary: Preview Margin Order Impact + operationId: previewMarginOrder + description: | + Previews the margin impact of a hypothetical spot order without actually placing it. + + Returns both pre-order and post-order margin risk statistics, allowing you to understand how an order would affect your margin account before execution. This is useful for risk management and planning trades. + + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `orders:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + ### Account Type + This endpoint is only available for margin trading accounts. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - symbol + - side + - type + properties: + request: + type: string + description: The literal string "/v1/margin/order/preview" + nonce: + $ref: '#/components/schemas/Nonce' + symbol: + type: string + description: The trading pair symbol (e.g., "btcusd") + example: "btcusd" + side: + type: string + enum: [buy, sell] + description: The order side + example: "buy" + type: + type: string + enum: [market, limit] + description: The order type + example: "limit" + amount: + type: string + format: decimal + description: The order amount in base currency (required for limit orders and sell market orders) + example: "0.5" + price: + type: string + format: decimal + description: The limit price (required for limit orders) + example: "50000.00" + totalSpend: + type: string + format: decimal + description: Total spend in quote currency (required for buy market orders) + example: "25000.00" + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group." + examples: + limitBuy: + summary: Limit Buy Order Preview + description: Preview a limit buy order + value: + request: "/v1/margin/order/preview" + nonce: + symbol: "btcusd" + side: "buy" + type: "limit" + amount: "0.5" + price: "50000.00" + marketBuy: + summary: Market Buy Order Preview + description: Preview a market buy order using total spend + value: + request: "/v1/margin/order/preview" + nonce: + symbol: "ethusd" + side: "buy" + type: "market" + totalSpend: "5000.00" + marketSell: + summary: Market Sell Order Preview + description: Preview a market sell order + value: + request: "/v1/margin/order/preview" + nonce: + symbol: "btcusd" + side: "sell" + type: "market" + amount: "0.25" + + responses: + '200': + description: Pre-order and post-order margin risk statistics + content: + application/json: + schema: + $ref: '#/components/schemas/MarginOrderPreview' + example: + preorder: + marginAssetValue: + currency: "USD" + value: "10000.00" + availableCollateral: + currency: "USD" + value: "8500.00" + notionalValue: + currency: "USD" + value: "15000.00" + totalBorrowed: + currency: "USD" + value: "5000.00" + leverage: "1.5" + reservedBuyOrders: + currency: "USD" + value: "0.00" + reservedSellOrders: + currency: "USD" + value: "0.00" + buyingPower: + currency: "USD" + value: "8500.00" + sellingPower: + currency: "USD" + value: "8500.00" + postorder: + marginAssetValue: + currency: "USD" + value: "10000.00" + availableCollateral: + currency: "USD" + value: "6000.00" + notionalValue: + currency: "USD" + value: "40000.00" + totalBorrowed: + currency: "USD" + value: "30000.00" + leverage: "4.0" + reservedBuyOrders: + currency: "USD" + value: "0.00" + reservedSellOrders: + currency: "USD" + value: "0.00" + buyingPower: + currency: "USD" + value: "6000.00" + sellingPower: + currency: "USD" + value: "6000.00" + liquidationRisk: + lossPercentage: "0.6000" + liquidationPrice: + currency: "USD" + value: "30000.00" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/heartbeat: + post: + x-zudoku-playground-enabled: false + tags: + - Session + summary: Heartbeat + operationId: sendHeartbeat + description: | + This will prevent a [session](/authentication/api-key#private-api-invocation) from timing out and canceling orders if the [require heartbeat](/authentication/api-key#require-heartbeat) flag has been set. Note that this is only required if no other private API requests have been made. The arrival of any message resets the heartbeat timer. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Heartbeat' + example: + request: "/v1/heartbeat" + nonce: + responses: + '200': + description: The heartbeat was received successfully + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: ok + description: ok + example: + result: ok + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/wrap/{symbol}: + post: + x-zudoku-playground-enabled: false + tags: + - Orders + summary: Wrap Order + operationId: wrapOrder + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `orders:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + parameters: + - $ref: '#/components/parameters/symbolParam' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - amount + properties: + request: + type: string + description: The literal string "/v1/wrap/symbol" + nonce: + $ref: '#/components/schemas/Nonce' + amount: + type: string + description: The amount to wrap + side: + type: string + enum: [buy, sell] + description: '"buy" or "sell"' + client_order_id: + type: string + description: A client-specified order id + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + example: + request: "/v1/wrap/GUSDUSD" + nonce: + amount: "1" + side: "buy" + client_order_id: "4ac6f45f-baf1-40f8-83c5-001e3ea73c7f" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + orderId: + type: string + description: The order ID + pair: + type: string + description: Trading pair symbol + price: + type: string + description: The price of the order + priceCurrency: + type: string + description: The currency in which the order is priced + side: + type: string + description: Either "buy" or "sell" + quantity: + type: string + description: The amount that was executed + quantityCurrency: + type: string + description: The currency label for the quantity field + totalSpend: + type: string + description: Total quantity spent for the order + totalSpendCurrency: + type: string + description: Currency of the totalSpend + fee: + type: string + description: The amount charged + feeCurrency: + type: string + description: Currency that the fee was paid in + depositFee: + type: string + description: The deposit fee quantity + depositFeeCurrency: + type: string + description: Currency in which depositFee is taken + example: + orderId: 429135395 + pair: "GUSDUSD" + price: "1" + priceCurrency: "USD" + side: "buy" + quantity: "1" + quantityCurrency: "GUSD" + totalSpend: "1" + totalSpendCurrency: "USD" + fee: "0" + feeCurrency: "USD" + depositFee: "0" + depositFeeCurrency: "USD" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/notionalbalances/{currency}: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Get Notional Balances + operationId: getNotionalBalances + description: | + + + This will show the available balances in the supported currencies as well as the notional value in the currency specified. + + + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `balances:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + parameters: + - $ref: '#/components/parameters/currencyParam' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/notionalbalances/currency" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + basic: + summary: Basic Request + description: Basic request to get notional balances in USD + value: + request: "/v1/notionalbalances/usd" + nonce: + withAccount: + summary: With Account Parameter + description: Request with account parameter for Master API keys + value: + request: "/v1/notionalbalances/usd" + nonce: + account: "primary" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/NotionalBalance' + example: + - currency: "BTC" + amount: "1154.62034001" + amountNotional: "10386000.59" + available: "1129.10517279" + availableNotional: "10161000.71" + availableForWithdrawal: "1129.10517279" + availableForWithdrawalNotional: "10161000.71" + - currency: "USD" + amount: "18722.79" + amountNotional: "18722.79" + available: "14481.62" + availableNotional: "14481.62" + availableForWithdrawal: "14481.62" + availableForWithdrawalNotional: "14481.62" + - currency: "ETH" + amount: "20124.50369697" + amountNotional: "100621.31" + available: "20124.50369697" + availableNotional: "100621.31" + availableForWithdrawal: "20124.50369697" + availableForWithdrawalNotional: "100621.31" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/addresses/{network}: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: List Deposit Addresses + operationId: listDepositAddresses + description: | + + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `addresses:read` or `addresses:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + parameters: + - $ref: '#/components/parameters/networkParam' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/addresses/network" + nonce: + $ref: '#/components/schemas/Nonce' + timestamp: + $ref: '#/components/schemas/TimestampType' + description: Only returns addresses created on or after this timestamp + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + basic: + summary: Basic Request + description: Basic request to get Bitcoin deposit addresses + value: + request: "/v1/addresses/bitcoin" + nonce: + withTimestamp: + summary: With Timestamp + description: Request with timestamp filter + value: + request: "/v1/addresses/ethereum" + nonce: + timestamp: 1591084414000 + withAccount: + summary: With Account Parameter + description: Request with account parameter for Master API keys + value: + request: "/v1/addresses/bitcoin" + nonce: + account: "primary" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Address' + examples: + bitcoinAddresses: + summary: Bitcoin Addresses + description: Response with Bitcoin deposit addresses + value: + - address: "n2saq73aDTu42bRgEHd8gd4to1gCzHxrdj" + timestamp: 1424285102000 + label: "my bitcoin address" + - address: "n2wpl14aJEu10bRgMNd0gdjH8dHJ3h2a3ks" + timestamp: 1824785101000 + ethereumAddresses: + summary: Ethereum Addresses + description: Response with Ethereum deposit addresses + value: + - address: "0x1f7a49d62d5256d0a80d31a07f57b578c3e40183" + timestamp: 1591084414000 + label: "main eth address" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/deposit/{network}/newAddress: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Create New Deposit Address + operationId: createNewDepositAddress + description: | + + + ### Roles + The API key you use to access this endpoint must have the Fund Manager role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `addresses:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + parameters: + - $ref: '#/components/parameters/networkParam' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/deposit/network/newAddress" + nonce: + $ref: '#/components/schemas/Nonce' + label: + type: string + description: A label for the address + legacy: + type: boolean + description: Whether to generate a legacy P2SH-P2PKH litecoin address. False by default. + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + basicBitcoin: + summary: Basic Bitcoin Address Request + description: Basic request to create a new Bitcoin deposit address + value: + request: "/v1/deposit/bitcoin/newAddress" + nonce: + label: "optional test label" + legacyLitecoin: + summary: Legacy Litecoin Address Request + description: Request to create a legacy Litecoin deposit address + value: + request: "/v1/deposit/litecoin/newAddress" + nonce: + label: "LTC legacy deposit address" + legacy: true + withAccount: + summary: With Account Parameter + description: Request with account parameter for Master API keys + value: + request: "/v1/deposit/ethereum/newAddress" + nonce: + label: "ETH deposit address" + account: "primary" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Address' + examples: + bitcoinAddress: + summary: Bitcoin Address + description: Response with a new Bitcoin deposit address + value: + network: "bitcoin" + address: "n2saq73aDTu42bRgEHd8gd4to1gCzHxrdj" + label: "optional test label" + litecoinAddress: + summary: Litecoin Address + description: Response with a new Litecoin deposit address + value: + network: "litecoin" + address: "MJRSgZ3UUFcTBTBAcN38XAXvZLwRe8WVw7" + label: "LTC legacy deposit address" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v2/transfers: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: List Past Transfers + operationId: listPastTransfers + description: | + + + This endpoint shows deposits and withdrawals in supported currencies with full multichain (multi-network) support. It returns accurate status information for transfers on **all supported networks** including Solana, Arbitrum, Optimism, Base, Avalanche, and Ethereum. + + Each transfer in the response includes a `network` field identifying the blockchain network, along with network-specific `feeAmount`, `feeCurrency`, and `txHash` values. + + This endpoint does not currently show cancelled advances, returned outgoing wires or ACH transactions, or other exceptional transaction circumstances. + + Fiat transfers between non-derivative and derivatives accounts are prohibited. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `history:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v2/transfers" + nonce: + $ref: '#/components/schemas/Nonce' + currency: + type: string + description: Currency code, see symbols and minimums + network: + type: string + description: Filter transfers by blockchain network (e.g., `ethereum`, `solana`, `arbitrum`, `optimism`, `base`, `avalanche`) + timestamp: + $ref: '#/components/schemas/TimestampType' + description: Only return transfers after this timestamp + limit_transfers: + type: integer + description: The maximum number of transfers to return. The default is 10 and the maximum is 50. + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + show_completed_deposit_advances: + type: boolean + description: Whether to display completed deposit advances. True by default. + examples: + basic: + summary: Basic Request + description: Basic request to get all transfers across all networks + value: + request: "/v2/transfers" + nonce: + withCurrency: + summary: With Currency Filter + description: Request with currency filter for USDC transfers + value: + request: "/v2/transfers" + nonce: + currency: "USDC" + withNetwork: + summary: With Network Filter + description: Request filtered to a specific network + value: + request: "/v2/transfers" + nonce: + currency: "USDC" + network: "solana" + withFilters: + summary: With Multiple Filters + description: Request with timestamp, limit, and account filters + value: + request: "/v2/transfers" + nonce: + timestamp: 1591084414000 + limit_transfers: 25 + account: "primary" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/V2Transfer' + examples: + multiNetworkTransfers: + summary: Multi-Network Transfers + description: Response with transfers across different networks + value: + - type: "Withdrawal" + status: "Complete" + timestampms: 1772818620354 + eid: 368598436530 + currency: "USDC" + amount: "0.01" + network: "ethereum" + feeAmount: "0.118856" + feeCurrency: "USDC" + txHash: "714a15c4fd2d37629d27e56a63aaec5f91e0053dde3eb357be71663c1197b391" + destination: "0x83cFb8C13f06716b449E5D24F5b4cc6Cc64a189A" + withdrawalId: "69ab0b0f-3c76-433d-84a5-c8bcc6718411" + - type: "Withdrawal" + status: "Complete" + timestampms: 1772034480391 + eid: 368474658614 + currency: "USDC" + amount: "1799" + network: "solana" + feeAmount: "0.202536" + feeCurrency: "USDC" + txHash: "4vJ9JU1bJJE96FWSJKvHsmmFADCg4gpZQff4P3bkLKi" + withdrawalId: "9b7a5100-b3ee-4820-9b5b-c2dd7db6559b" + - type: "Deposit" + status: "Advanced" + timestampms: 1771990797452 + eid: 309356152 + currency: "ETH" + amount: "100" + network: "ethereum" + feeAmount: "0" + feeCurrency: "ETH" + txHash: "605c5fa8bf99458d24d61e09941bc443ddc44839d9aaa508b14b296c0c8269b2" + adminTransactions: + summary: Administrative Transactions + description: Response with administrative credits and debits (no network field) + value: + - type: "AdminDebit" + status: "Complete" + timestampms: 1626990636645 + eid: 1001248356 + currency: "BTC" + amount: "6" + purpose: "Administrative debit" + - type: "AdminCredit" + status: "Complete" + timestampms: 1626990476421 + eid: 1001245359 + currency: "BTC" + amount: "4" + purpose: "Fee reimbursement credit" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/custodyaccountfees: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: List Custody Fee Transfers + operationId: listCustodyFeeTransfers + description: | + + + This endpoint shows Custody fee records in the supported currencies. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `history:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/custodyaccountfees" + nonce: + $ref: '#/components/schemas/Nonce' + timestamp: + $ref: '#/components/schemas/TimestampType' + description: Only return Custody fee records on or after this timestamp + limit_transfers: + type: integer + description: The maximum number of Custody fee records to return. The default is 10 and the maximum is 50. + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + basic: + summary: Basic Request + description: Basic request to get custody account fees + value: + request: "/v1/custodyaccountfees" + nonce: + withFilters: + summary: With Filters + description: Request with timestamp and limit filters + value: + request: "/v1/custodyaccountfees" + nonce: + timestamp: 1652279000000 + limit_transfers: 20 + withAccount: + summary: With Account Parameter + description: Request with account parameter for Master API keys + value: + request: "/v1/custodyaccountfees" + nonce: + account: "primary" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/CustodyFeeTransfer' + examples: + multipleFees: + summary: Multiple Fee Records + description: Response with multiple custody fee records + value: + - txTime: 1657236174056 + feeAmount: "10" + feeCurrency: "BTC" + eid: 256627 + eventType: "Withdrawal" + - txTime: 1652279045196 + feeAmount: "10000000" + feeCurrency: "ETH" + eid: 15364 + eventType: "CustodyFeeDebit" + - txTime: 1652279025196 + feeAmount: "1850" + feeCurrency: "WFIL" + eid: 9016 + eventType: "RiaFeeDebit" + - txTime: 1652279025196 + feeAmount: "1850" + feeCurrency: "WFIL" + eid: 9016 + eventType: "RiaFeeCredit" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v2/withdraw/{network}/{ticker}/feeEstimate: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Get Gas Fee Estimation + operationId: getGasFeeEstimation + description: | + + + API users will not be aware of the transfer fees before starting the withdrawal process. This endpoint allows you to find out the estimated gas fees before you start a withdrawal. It requires specifying the blockchain network and ticker, which is useful for tokens that exist on multiple networks (e.g. USDC on Ethereum vs Solana). + + ### Roles + The API key you use to access this endpoint can have the Trader, Fund Manager, Auditor, WealthManager or Administrator role assigned. See [Roles](#roles) for more information. + + parameters: + - name: network + in: path + description: The blockchain network for the withdrawal (e.g. `ethereum`, `bitcoin`, `solana`) + required: true + schema: + type: string + example: ethereum + - name: ticker + in: path + description: The currency code for the withdrawal (e.g. `eth`, `btc`, `sol`, `usdc`) + required: true + schema: + type: string + example: eth + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + description: Sample payload for ETH fee estimation on Ethereum network + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/FeeEstimateV2Request' + examples: + ethOnEthereum: + summary: ETH on Ethereum + description: Estimate withdrawal fee for ETH on Ethereum network + value: + request: "/v2/withdraw/ethereum/eth/feeEstimate" + nonce: + address: "0x31c2105b8dea834167f32f7ea7d877812e059230" + amount: "0.01" + usdcOnSolana: + summary: USDC on Solana + description: Estimate withdrawal fee for USDC on Solana network + value: + request: "/v2/withdraw/solana/usdc/feeEstimate" + nonce: + address: "7EcDhSYGxXyscszYEp35KHN8vvw3svAuLKTzXwCFLtV" + amount: "100" + btcOnBitcoin: + summary: BTC on Bitcoin + description: Estimate withdrawal fee for BTC on Bitcoin network + value: + request: "/v2/withdraw/bitcoin/btc/feeEstimate" + nonce: + address: "mi98Z9brJ3TgaKsmvXatuRahbFRUFKRUdR" + amount: "0.5" + responses: + '200': + description: Successful fee estimation response + content: + application/json: + schema: + $ref: '#/components/schemas/FeeEstimateV2Response' + examples: + ethResponse: + summary: ETH Fee Estimate Response + description: JSON response for ETH withdrawal fee estimate + value: + currency: "ETH" + fee: 0.001 + isOverride: false + monthlyLimit: 1 + monthlyRemaining: 1 + usdcOnSolanaResponse: + summary: USDC on Solana Fee Estimate Response + description: JSON response for USDC on Solana withdrawal fee estimate + value: + currency: "USDC" + fee: 0.01 + isOverride: false + monthlyLimit: 10 + monthlyRemaining: 8 + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + + /v2/withdraw/{network}/{ticker}: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Withdraw Crypto Funds + operationId: withdrawCryptoFunds + description: | + + + Withdraw cryptocurrency funds to an approved address, with explicit network selection. + + The key improvement over v1 is the explicit `network` path parameter, which allows you to specify exactly which blockchain network to use for the withdrawal. This is especially important for tokens available on multiple networks (e.g., USDC on Ethereum, Solana, Base, Arbitrum, etc.). + + Before you can withdraw cryptocurrency funds to an approved address, you need three things: + + 1. You must have an approved address list for your account + 2. The address you want to withdraw funds to needs to already be on that approved address list + 3. An API key with the Fund Manager role added + + If you would like to withdraw via API to addresses that are not on your approved address list, please reach out to trading@gemini.com. We can enable this feature for you provided a set of approved IP addresses. This functionality is only available for exchange accounts. Pre-approved IP addresses and addresses added to your approved address list are required to enable withdrawal APIs for custody accounts. + + Use the [Get Network](/rest/market-data#get-network) endpoint to discover which networks support withdrawals for a given token. + + See [Roles](/roles#roles) for more information on how to add the Fund Manager role to the API key you want to use. + + ### Roles + The API key you use to access this endpoint must have the Fund Manager role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `crypto:send` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + parameters: + - $ref: '#/components/parameters/networkParam' + - name: ticker + in: path + required: true + schema: + type: string + description: The cryptocurrency ticker code (e.g., `btc`, `eth`, `usdc`). See [Symbols and minimums](/market-data/symbols-and-minimums). + example: eth + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - address + - amount + properties: + address: + type: string + description: The destination address for the withdrawal + amount: + type: string + description: The amount to withdraw + memo: + type: string + description: Required for certain networks that use memos (e.g., Solana, XRP, Cosmos). The destination tag or memo for the withdrawal. + clientTransferId: + type: string + format: uuid + description: A unique UUID for idempotent withdrawals. If provided, duplicate requests with the same `clientTransferId` will not create additional withdrawals. + examples: + btcWithdrawal: + summary: BTC Withdrawal on Bitcoin + description: JSON payload for BTC withdrawal on the Bitcoin network + value: + address: "mi98Z9brJ3TgaKsmvXatuRahbFRUFKRUdR" + amount: "1" + ethWithdrawal: + summary: ETH Withdrawal on Ethereum + description: JSON payload for ETH withdrawal on the Ethereum network with client transfer ID + value: + address: "0xA63123350Acc8F5ee1b1fBd1A6717135e82dBd28" + amount: "2.34567" + clientTransferId: "AA97B177-9383-4934-8543-0F91A7A02838" + usdcWithdrawalSolana: + summary: USDC Withdrawal on Solana + description: JSON payload for USDC withdrawal on the Solana network + value: + address: "7EcDhSYGxXyscszYEp35KHN8vvw3svAuLKTzXwCFLtV" + amount: "100" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/WithdrawCryptoFundsResponse' + examples: + btcWithdrawalResponse: + summary: BTC Withdrawal Response + description: JSON response for BTC withdrawal on Bitcoin network + value: + withdrawalId: "02176a83-a6b1-4202-9b85-1c1c92dd25c4" + address: "mi98Z9brJ3TgaKsmvXatuRahbFRUFKRUdR" + amount: "1" + currency: "BTC" + fee: "0" + ethWithdrawalResponse: + summary: ETH Withdrawal Response + description: JSON response for ETH withdrawal on Ethereum network + value: + withdrawalId: "82de1a28-05a5-4f5c-9b3a-d78b1e3e0c91" + address: "0xA63123350Acc8F5ee1b1fBd1A6717135e82dBd28" + amount: "2.34567" + currency: "ETH" + fee: "0.001" + usdcWithdrawalSolanaResponse: + summary: USDC Withdrawal on Solana Response + description: JSON response for USDC withdrawal on Solana network + value: + withdrawalId: "f4a1c7b3-2e8d-4a9f-b6c5-1d3e7f8a9b0c" + address: "7EcDhSYGxXyscszYEp35KHN8vvw3svAuLKTzXwCFLtV" + amount: "100" + currency: "USDC" + fee: "0" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/clearing/new: + post: + x-zudoku-playground-enabled: false + tags: + - Clearing + summary: Create New Clearing Order + operationId: createNewClearingOrder + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `clearing:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - symbol + - amount + - price + - side + properties: + request: + type: string + description: The literal string "/v1/clearing/new" + nonce: + $ref: '#/components/schemas/Nonce' + symbol: + type: string + description: The trading pair + amount: + type: string + description: The amount to trade + price: + type: string + description: The price + side: + type: string + enum: [buy, sell] + description: The direction of the trade + counterparty_id: + type: string + description: The counterparty ID + expires_in_hrs: + type: integer + description: The number of hours until the order expires + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + newClearingOrder: + summary: New Clearing Order + description: JSON payload for creating a new clearing order + value: + request: "/v1/clearing/new" + nonce: + counterparty_id: "OM9VNL1G" + expires_in_hrs: 24 + symbol: "btcusd" + amount: "100" + price: "9500.00" + side: "buy" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ClearingOrder' + example: + result: "AwaitConfirm" + clearing_id: "0OQGOZXW" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/clearing/status: + post: + x-zudoku-playground-enabled: false + tags: + - Clearing + summary: Get Clearing Order + operationId: getClearingOrder + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `clearing:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - clearing_id + properties: + request: + type: string + description: The literal string "/v1/clearing/status" + nonce: + $ref: '#/components/schemas/Nonce' + clearing_id: + type: string + description: The clearing ID + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + orderStatusRequest: + summary: Order Status Request + description: JSON payload for checking clearing order status + value: + request: "/v1/clearing/status" + nonce: + clearing_id: "OM9VNL1G" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ClearingOrder' + example: + result: "ok" + status: "Confirmed" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/clearing/cancel: + post: + x-zudoku-playground-enabled: false + tags: + - Clearing + summary: Cancel Clearing Order + operationId: cancelClearingOrder + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `clearing:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - clearing_id + properties: + request: + type: string + description: The literal string "/v1/clearing/cancel" + nonce: + $ref: '#/components/schemas/Nonce' + clearing_id: + type: string + description: The clearing ID + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + cancelOrderRequest: + summary: Cancel Order Request + description: JSON payload for canceling a clearing order + value: + request: "/v1/clearing/cancel" + nonce: + clearing_id: "P0521QDV" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + result: + type: string + description: Status of the cancel operation + details: + type: string + description: Detailed description of the result + examples: + successfulCancel: + summary: Successful Cancel + description: JSON response for successful order cancellation + value: + result: "ok" + details: "P0521QDV order canceled" + failedCancel: + summary: Failed Cancel + description: JSON response for failed order cancellation + value: + result: "failed" + details: "Unable to cancel order P0521QDV" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/clearing/confirm: + post: + x-zudoku-playground-enabled: false + tags: + - Clearing + summary: Confirm Clearing Order + operationId: confirmClearingOrder + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `clearing:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - clearing_id + - symbol + - amount + - price + - side + properties: + request: + type: string + description: The literal string "/v1/clearing/confirm" + nonce: + $ref: '#/components/schemas/Nonce' + clearing_id: + type: string + description: The clearing ID + symbol: + type: string + description: The trading pair + amount: + type: string + description: The amount to trade + price: + type: string + description: The price + side: + type: string + enum: [buy, sell] + description: The direction of the trade + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + confirmOrderRequest: + summary: Confirm Order Request + description: JSON payload for confirming a clearing order + value: + request: "/v1/clearing/confirm" + nonce: + clearing_id: "OM9VNL1G" + symbol: "btcusd" + amount: "100" + price: "9500.00" + side: "sell" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + result: + type: string + description: Status of the confirmation operation + examples: + successfulConfirm: + summary: Successful Confirmation + description: JSON response for successful order confirmation + value: + result: "confirmed" + failedConfirm: + summary: Failed Confirmation + description: JSON response for failed order confirmation + value: + result: "error" + reason: "InvalidSide" + message: "Invalid side for symbol BTCUSD: 'buy'" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/clearing/list: + post: + x-zudoku-playground-enabled: false + tags: + - Clearing + summary: List Clearing Orders + operationId: listClearingOrders + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `clearing:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/clearing/list" + nonce: + $ref: '#/components/schemas/Nonce' + symbol: + type: string + description: Trading pair + counterparty: + type: string + description: counterparty_id or counterparty_alias + side: + type: string + enum: [buy, sell] + description: '"buy" or "sell"' + expiration_start: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp. Requires `expiration_end` if set + expiration_end: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp. Requires `expiration_start` if set + submission_start: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp. Requires `submission_end` if set + submission_end: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp. Requires `submission_start` if set + funded: + type: boolean + description: Default value false if not set + status: + type: string + description: Filter by status + timestamp: + $ref: '#/components/schemas/TimestampType' + description: Only return orders after this timestamp + limit_orders: + type: integer + description: The maximum number of orders to return + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + basic: + summary: Basic Request + description: Basic request to get clearing orders + value: + request: "/v1/clearing/list" + nonce: + withFilters: + summary: With Filters + description: Request with multiple filters + value: + request: "/v1/clearing/list" + nonce: + symbol: "BTCEUR" + counterparty: "KQ4P3XWE" + side: "buy" + expiration_start: 1642222800000 + expiration_end: 1642309200000 + submission_start: 1641790800000 + submission_end: 1641791100000 + funded: false + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + result: + type: string + description: Status of the operation + orders: + type: array + items: + type: object + properties: + clearing_id: + type: string + description: A unique identifier for the clearing order + order_id: + type: string + description: Only provided if order was submitted with it + counterparty_id: + type: string + description: A symbol that corresponds with a counterparty + counterparty_alias: + type: string + description: Counterparty alias + broker_id: + type: string + description: A symbol that corresponds with a broker id + symbol: + type: string + description: Trading pair + side: + type: string + enum: [buy, sell] + description: '"buy" or "sell"' + price: + type: number + format: decimal + description: The price the clearing order was executed at + quantity: + type: number + format: decimal + description: The amount that was executed + status: + type: string + description: A description of the status of the order + submission: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp + expiration: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp + examples: + successfulList: + summary: Successful List + description: JSON response with clearing orders + value: + result: "success" + orders: [ + { + clearing_id: "9LVQE9X5", + counterparty_id: "YZ43LX81", + symbol: "BTCEUR", + side: "sell", + price: 2, + quantity: 10, + status: "AwaitTargetConfirm", + submission: 1641790800020, + expiration: 1641963600000 + }, + { + clearing_id: "2MYR07XP", + order_id: "trade1SrcOrderId", + counterparty_id: "KQ4P3XWE", + broker_id: "WV4V1DGN", + symbol: "BTCEUR", + side: "buy", + price: 1, + quantity: 50, + status: "AwaitSourceConfirm", + submission: 1641790800016, + expiration: 1642222800000 + }, + { + clearing_id: "EM8WO7LQ", + order_id: "trade4SrcOrderId", + broker_id: "WV4V1DGN", + symbol: "BTCEUR", + side: "buy", + price: 4, + quantity: 8, + status: "AwaitSourceTargetConfirm", + submission: 1641790800028, + expiration: 1642136400000 + } + ] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/clearing/broker/list: + post: + x-zudoku-playground-enabled: false + tags: + - Clearing + summary: List Clearing Brokers + operationId: listClearingBrokers + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `clearing:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/clearing/broker/list" + nonce: + $ref: '#/components/schemas/Nonce' + symbol: + type: string + description: Trading pair + expiration_start: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp. Requires `expiration_end` if set + expiration_end: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp. Requires `expiration_start` if set + submission_start: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp. Requires `submission_end` if set + submission_end: + $ref: '#/components/schemas/TimestampType' + description: UTC timestamp. Requires `submission_start` if set + funded: + type: boolean + description: Default value false if not set + status: + type: string + description: Filter by status + timestamp: + $ref: '#/components/schemas/TimestampType' + description: Only return orders after this timestamp + limit_orders: + type: integer + description: The maximum number of orders to return + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + examples: + basic: + summary: Basic Request + description: Basic request to get broker clearing orders + value: + request: "/v1/clearing/broker/list" + nonce: + withFilters: + summary: With Filters + description: Request with multiple filters + value: + request: "/v1/clearing/broker/list" + nonce: + symbol: "BTCEUR" + expiration_start: 1642222800000 + expiration_end: 1642309200000 + submission_start: 1641790800000 + submission_end: 1641791100000 + funded: false + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + result: + type: string + description: Status of the operation + orders: + type: array + items: + type: object + properties: + clearing_id: + type: string + description: A unique identifier for the clearing order + source_counterparty_id: + type: string + description: Source counterparty id + source_order_id: + type: string + description: Only provided if order was submitted with it + target_counterparty_id: + type: string + description: Only provided if target counterparty was already set + target_order_id: + type: string + description: Only provided if target counterparty set this field + symbol: + type: string + description: Trading pair + source_side: + type: string + enum: [buy, sell] + description: '"buy" or "sell"' + price: + type: number + format: decimal + description: The price the clearing order was executed at + quantity: + type: number + format: decimal + description: The amount that was executed + status: + type: string + description: A description of the status of the order + submission: + type: integer + description: UTC timestamp + expiration: + type: integer + description: UTC timestamp + examples: + successfulList: + summary: Successful List + description: JSON response with broker clearing orders + value: + result: "success" + orders: [ + { + clearing_id: "9LVQ98X5", + source_counterparty_id: "R54L3DG1", + source_order_id: "trade1SrcOrderId", + target_counterparty_id: "KQ4P3XWE", + target_order_id: "trade1TgtOrderId", + symbol: "BTCEUR", + source_side: "buy", + price: 1, + quantity: 50, + status: "AwaitSourceConfirm", + submission: 1641790800016, + expiration: 1642222800000 + }, + { + clearing_id: "VXQ341X4", + source_counterparty_id: "R54L3DG1", + source_order_id: "trade4SrcOrderId", + symbol: "BTCEUR", + source_side: "buy", + price: 4, + quantity: 8, + status: "AwaitSourceTargetConfirm", + submission: 1641790800028, + expiration: 1642136400000 + } + ] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/clearing/broker/new: + post: + x-zudoku-playground-enabled: false + tags: + - Clearing + summary: Create New Broker Order + operationId: createNewBrokerOrder + description: | + Gemini Clearing also allows for brokers to facilitate trades between two Gemini customers. A broker can submit a new Gemini Clearing order that must then be confirmed by each counterparty before settlement. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - source_counterparty_id + - target_counterparty_id + - symbol + - amount + - expires_in_hrs + - price + - side + properties: + request: + type: string + description: The literal string "/v1/clearing/broker/new" + nonce: + $ref: '#/components/schemas/Nonce' + source_counterparty_id: + type: string + description: A symbol that corresponds with the counterparty sourcing the clearing trade + target_counterparty_id: + type: string + description: A symbol that corresponds with the counterparty where the clearing trade is targeted + symbol: + type: string + description: The [symbol](/market-data/symbols-and-minimums) of the order + amount: + type: string + format: decimal + description: Quoted decimal amount to purchase + expires_in_hrs: + type: integer + format: float + description: The number of hours before the trade expires. Your counterparty will need to confirm the order before this time expires. + price: + type: string + format: decimal + description: Quoted decimal amount to spend per unit + side: + type: string + enum: [buy, sell] + description: | + "buy" or "sell". This side will be assigned to the `source_counterparty_id`. The opposite side will be sent to the `target_counterparty_id` + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the broker account on which to place the order. Only available for exchange accounts. + examples: + brokerOrderInitiation: + summary: Broker order initiation sample + description: Sample payload for broker order initiation + value: + request: "/v1/clearing/broker/new" + nonce: + source_counterparty_id: R485E04Q + target_counterparty_id: Z4929ZDY + symbol: ethusd + amount: "175.00" + expires_in_hrs: 1.0 + price: "200" + side: sell + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + result: + type: string + description: Will return `AwaitSourceTargetConfirm`, meaning the order is waiting for both the source and the target parties to confirm the order + clearing_id: + type: string + description: A unique identifier for the clearing order. + example: { + result: AwaitSourceTargetConfirm, + clearing_id: "8EM7NVXD" + } + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/clearing/trades: + post: + x-zudoku-playground-enabled: false + tags: + - Clearing + summary: List Clearing Trades + operationId: listClearingTrades + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `clearing:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/clearing/trades" + nonce: + $ref: '#/components/schemas/Nonce' + timestamp_nanos: + type: integer + description: Only return transfers on or after this timestamp in nanos + limit_per_account: + type: integer + description: The maximum number of clearing trades to return. The default is 100 and the maximum is 300. + account: + type: string + description: Only required when using a master api-key. The name of the account within the subaccount group. + symbol: + type: string + description: The trading pair + timestamp: + $ref: '#/components/schemas/TimestampType' + description: Only return trades after this timestamp + limit_trades: + type: integer + description: The maximum number of trades to return + examples: + basic: + summary: Basic Request + description: Basic request to get clearing trades + value: + request: "/v1/clearing/trades" + nonce: + withTimestamp: + summary: With Timestamp + description: Request with timestamp filter + value: + request: "/v1/clearing/trades" + nonce: + timestamp_nanos: 1630382206000000000 + limit_per_account: 50 + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + results: + type: array + items: + type: object + properties: + sourceAccount: + type: string + description: A account that corresponds with the counterparty sourcing the clearing trade + targetAccount: + type: string + description: A account that corresponds with the counterparty where the clearing trade is targeted + pair: + type: string + description: The trading pair of the clearing trade + sourceSide: + type: string + enum: [buy, sell] + description: '"buy" or "sell"' + price: + type: string + description: The price the clearing order was executed at + quantity: + type: string + description: The amount that was executed + clearingId: + type: string + description: The clearing ID + status: + type: string + description: A description of the status of the order + expirationTimeMs: + $ref: '#/components/schemas/TimestampType' + description: The time that the clearing trade expires + createdMs: + $ref: '#/components/schemas/TimestampType' + description: The time that the clearing trade was created + lastUpdatedMs: + $ref: '#/components/schemas/TimestampType' + description: The last time the clearing trade was updated + hasBroker: + type: boolean + description: Broker trade + wasNotified: + type: boolean + description: Broker was notified + examples: + successfulTrades: + summary: Successful Trades + description: JSON response with clearing trades + value: + results: [ + { + sourceAccount: "primary", + targetAccount: "primary", + pair: "BTCUSD", + sourceSide: "buy", + price: "1", + quantity: "1000", + clearingId: "41M23L5Q", + status: "Settled", + expirationTimeMs: 1662567706120, + createdMs: 1662481306139, + lastUpdatedMs: 1662481561668, + hasBroker: false, + wasNotified: false + }, + { + sourceAccount: "primary", + targetAccount: "primary", + pair: "BTCUSD", + sourceSide: "buy", + price: "12", + quantity: "1000", + clearingId: "0EMOYLJ5", + status: "AwaitTargetConfirm", + expirationTimeMs: 1662567728123, + createdMs: 1662481328126, + lastUpdatedMs: 1662481561415, + hasBroker: false, + wasNotified: true + } + ] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + /v1/instant/quote: + post: + x-zudoku-playground-enabled: false + tags: + - Instant + summary: Get Instant Quote + operationId: getInstantQuote + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `orders:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - side + - symbol + - nonce + - totalSpend + properties: + request: + type: string + description: The literal string "/v1/instant/quote/" + side: + type: string + enum: [buy, sell] + description: '"buy" or "sell"' + symbol: + type: string + description: The [symbol](/market-data/symbols-and-minimums) for the order. Instant includes order books denominated in a [supported currency](https://support.gemini.com/hc/en-us/articles/360000032663-Does-Gemini-support-fiat-currencies-other-than-USD), as `CCY2` + nonce: + $ref: '#/components/schemas/Nonce' + totalSpend: + type: string + description: Quoted decimal amount to spend on the order. Must comply with [stated minimums](/market-data/symbols-and-minimums). The `totalSpend` will be `CCY2` in `buy` orders and `CCY1` in `sell` orders. + paymentMethodUuid: + type: string + description: uuid provided as `bankId` in [Payment Methods API](/fund-management#list-payment-methods) + paymentMethodType: + type: string + description: Method used to specify payment method in `buy` order. Can be "AccountBalancePaymentType" to use funds available in USD balance held on Gemini, "BankAccountType" to initial an ACH from a linked bank account, or "CardAccountType" to use a linked debit card to fund the purchase. + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + examples: + buyQuote: + summary: Buy Quote Request + description: JSON payload for BTCUSD buy quote + value: + request: "/v1/instant/quote" + nonce: + symbol: "btcusd" + side: "buy" + totalSpend: "100" + sellQuote: + summary: Sell Quote Request + description: JSON payload for ETHUSD sell quote + value: + request: "/v1/instant/quote" + nonce: + symbol: "ethusd" + side: "sell" + totalSpend: "1" + responses: + '200': + description: Sample Responses + content: + application/json: + schema: + $ref: '#/components/schemas/InstantQuote' + examples: + btcBuyResponse: + summary: BTC Buy Quote Response + description: Sample BTCUSD Buy Response + value: + quoteId: 1328 + maxAgeMs: 60000 + pair: BTCUSD + price: "6445.07" + priceCurrency: USD + side: buy + quantity: "0.01505181" + quantityCurrency: BTC + fee: "2.9900309233" + feeCurrency: USD + depositFee: "0" + depositFeeCurrency: USD + totalSpend: "100" + totalSpendCurrency: USD + ethSellResponse: + summary: ETH Sell Quote Response + description: Sample ETHUSD Sell Response + value: + quoteId: 20930 + maxAgeMs: 60000 + pair: ETHUSD + price: "225.42" + priceCurrency: USD + side: sell + quantity: "1" + quantityCurrency: ETH + fee: "2.99" + feeCurrency: USD + depositFee: "0" + depositFeeCurrency: USD + totalSpend: "1" + totalSpendCurrency: ETH + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/instant/execute: + post: + x-zudoku-playground-enabled: false + tags: + - Instant + summary: Execute Instant Order + operationId: executeInstantOrder + description: | + ### Roles + The API key you use to access this endpoint must have the Trader role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `orders:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - quoteId + - symbol + - side + - quantity + - price + - fee + properties: + request: + type: string + description: The literal string "/v1/instant/execute" + nonce: + $ref: '#/components/schemas/Nonce' + symbol: + type: string + description: The symbol for the order. + side: + type: string + enum: [buy, sell] + description: '"buy" or "sell"' + quantity: + type: string + description: The quantity of the asset bought or sold. quantity must match quantity returned in the quote + price: + type: string + description: The price from the quote. price must match price returned in the quote + fee: + type: string + description: The fee for the order. fee must match fee returned in the quote + quoteId: + type: integer + description: Unique ID for the quote. quoteId must match quoteId returned in the quote + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + examples: + executeBuyOrder: + summary: Execute Buy Instant Order + description: Sample Instant Order Execution Request Payload BTCUSD Buy + value: + request: "/v1/instant/execute" + nonce: + symbol: BTCUSD + side: buy + quantity: "0.01505181" + price: "6445.07" + fee: "2.9900309233" + quoteId: 1328 + executeSellOrder: + summary: Execute Sell Instant Order + description: Sample Instant Order Execution Request Payload ETHUSD Sell + value: + request: "/v1/instant/execute" + nonce: + symbol: ETHUSD + side: sell + quantity: "1" + price: "225.42" + fee: "2.99" + quoteId: 20930 + + responses: + '200': + description: JSON response + content: + application/json: + schema: + type: object + properties: + orderId: + type: integer + description: The ID for the executed order + pair: + type: string + description: The symbol for the order. + price: + type: string + description: The price at which the order was executed + priceCurrency: + type: string + description: The currency in which the order is priced. Matches `CCY2` in the symbol + side: + type: string + description: Either "buy" or "sell" + quantity: + type: string + description: The quantity of the asset bought or sold + quantityCurrency: + type: string + description: The currency label for the `quantity` field. + totalSpend: + type: string + description: Total quantity to spend for the order. Will be the sum inclusive of all fees and amount to be traded. + totalSpendCurrency: + type: string + description: Currency of the `totalSpend` to be spent on the order + fee: + type: string + description: The fee quantity charged for the order + feeCurrency: + type: string + description: The currency label for the fee. + depositFee: + type: string + description: The deposit fee quantity. Will be applied if a debit card is used for the order. Will return 0 if there is no `depositFee` + depositFeeCurrency: + type: string + description: Currency in which `depositFee` is taken + examples: + btcusdBuy: + summary: Sample BTCUSD Buy + description: Sample Response BTCUSD Buy + value: + orderId: 375089415 + pair: BTCUSD + price: "6445.07" + priceCurrency: USD + side: buy + quantity: "0.01505181" + quantityCurrency: BTC + totalSpend: "100" + totalSpendCurrency: USD + fee: "2.9900309233" + feeCurrency: USD + depositFee: "0" + depositFeeCurrency: USD + ethusdSell: + summary: Sample ETHUSD Sell + description: Sample Response ETHUSD Sell + value: + orderId: 377326322 + pair: ETHUSD + price: "225.42" + priceCurrency: USD + side: sell + quantity: "1" + quantityCurrency: ETH + totalSpend: "0.1" + totalSpendCurrency: ETH + fee: "2.99" + feeCurrency: USD + depositFee: "0" + depositFeeCurrency: USD + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/payments/addbank: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Add Bank + operationId: addBank + description: | + The add bank API allows for banking information to be sent in via API. However, for the bank to be verified, you must still send in a wire for any amount from the bank account. + + ### Roles + This API requires the FundManager role. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `banks:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - accountnumber + - routing + - type + - name + properties: + request: + type: string + description: The literal string "/v1/payments/addbank" + nonce: + $ref: '#/components/schemas/Nonce' + accountnumber: + type: string + description: Account number of bank account to be added + routing: + type: string + description: Routing number of bank account to be added + type: + type: string + enum: [checking, savings] + description: Type of bank account to be added. Accepts `checking` or `savings` + name: + type: string + description: The name of the bank account as shown on your account statements + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Master API keys can get all account names using the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + example: + request: "/v1/payments/addbank" + nonce: + accountnumber: "account-number-string" + routing: "routing-number-string" + type: "checking" + name: "Satoshi Nakamoto Checking" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AddBankResponse' + example: + referenceId: "BankAccountRefId(18428)" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/payments/addbank/cad: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Add Bank CAD + operationId: addBankCAD + description: | + The add bank API allows for CAD banking information to be sent in via API. However, for the bank to be verified, you must still send in a wire for any amount from the bank account. + + ### Roles + This API requires the FundManager role. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `banks:create` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - swiftcode + - accountNumber + - type + - name + properties: + request: + type: string + description: The literal string "/v1/payments/addbank/cad" + nonce: + $ref: '#/components/schemas/Nonce' + swiftcode: + type: string + description: The account SWIFT code + accountNumber: + type: string + description: Account number of bank account to be added + institutionNumber: + type: string + description: The institution number of the account - optional but recommended. + branchnnumber: + type: string + description: The branch number - optional but recommended. + type: + type: string + enum: [checking, savings] + description: Type of bank account to be added. Accepts `checking` or `savings` + name: + type: string + description: The name of the bank account as shown on your account statements + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Master API keys can get all account names using the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + example: + request: "/v1/payments/addbank/cad" + nonce: + swiftcode: "swift-code-string" + accountnumber: "account-number-string" + institutionnumber: "institution-number-string" + branchnumber: "branch-number-string" + type: "checking" + name: "Satoshi Nakamoto Checking" + account: "account-string" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + result: + type: string + description: Status of the request. "OK" indicates the account has been created successfully. + example: + result: "OK" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/payments/methods: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: List Payment Methods + operationId: listPaymentMethods + description: | + The payments methods API will return data on balances in the account and linked banks. + + ### Roles + The API key you use to access this endpoint can be either a Master or Account level key with any role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `banks:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/payments/methods" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Master API keys can get all account names using the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + example: + request: "/v1/payments/methods" + account: "primary" + nonce: + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/PaymentMethodsResponse' + example: + balances: + - type: "exchange" + currency: "USD" + amount: "50893484.26" + available: "50889972.01" + availableForWithdrawal: "50889972.01" + banks: + - bank: "Jpmorgan Chase Bank Checking - 1111" + bankId: "97631a24-ca40-4277-b3d5-38c37673d029" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/account: + post: + x-zudoku-playground-enabled: false + tags: + - Account Administration + summary: Get Account Detail + operationId: getAccountDetail + description: | + The account API will return detail about the specific account requested such as users, country codes, etc. + + ### Roles + The API key you use to access this endpoint can be either a Master or Account level key with any role assigned. See [Roles](/roles#roles) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/account" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Master API keys can get all account names using the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + example: + request: "/v1/account" + account: "primary" + nonce: + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + account: + type: object + description: Contains information on the requested account + properties: + accountName: + type: string + description: The name of the account provided upon creation. Will default to `Primary` + shortName: + type: string + description: Nickname of the specific account (will take the name given, remove all symbols, replace all " " with "-" and make letters lowercase) + type: + type: string + description: The type of account. Will return either `exchange` or `custody` + created: + $ref: '#/components/schemas/TimestampType' + description: The timestamp of account creation, displayed as number of milliseconds since 1970-01-01 UTC. This will be transmitted as a JSON number + users: + type: array + description: Contains an array of JSON objects with user information for the requested account + items: + type: object + properties: + name: + type: string + description: Full legal name of the user + lastSignIn: + type: string + description: Timestamp of the last sign for the user. Formatted as yyyy-MM-dd'T'HH:mm:ss.SSS'Z' + status: + type: string + description: Returns user status. Will inform of `active` users or otherwise not active + countryCode: + type: string + description: 2 Letter country code indicating residence of user + isVerified: + type: boolean + description: Returns verification status of user + memo_reference_code: + type: string + description: Returns wire memo reference code for linked bank account + virtual_account_number: + type: string + description: Virtual account number for the account. Only populated if applicable for the account + example: + account: + accountName: "Primary" + shortName: "primary" + type: "exchange" + created: "1498245007981" + users: + - name: "Satoshi Nakamoto" + lastSignIn: "2020-07-21T13:37:39.453Z" + status: "Active" + countryCode: "US" + isVerified: true + - name: "Gemini Support" + lastSignIn: "2018-07-11T20:04:36.073Z" + status: "Suspended" + countryCode: "US" + isVerified: false + memo_reference_code: "GEMPJBRDZ" + virtual_account_number: "123456" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/approvedAddresses/account/{network}: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: List Approved Addresses + operationId: listApprovedAddresses + description: | + Allows viewing of Approved Address list. + + ### Roles + This API can accept any role. See [Roles](/roles#roles) for more information. + + parameters: + - $ref: '#/components/parameters/networkParam' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/approvedAddresses/account/:network" where `:network` can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to view the approved address list. + example: + request: "/v1/approvedAddresses/account/ethereum" + nonce: + account: "primary" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApprovedAddressesResponse' + example: + approvedAddresses: [ + { + network: "ethereum", + scope: "account", + label: "api_added_ETH_address", + status: "pending-time", + createdAt: "1602692572349", + address: "0x0000000000000000000000000000000000000000" + }, + { + network: "ethereum", + scope: "group", + label: "api_added_ETH_address", + status: "pending-time", + createdAt: "1602692542296", + address: "0x0000000000000000000000000000000000000000" + }, + { + network: "ethereum", + scope: "group", + label: "hardware_wallet", + status: "active", + createdAt: "1602087433270", + address: "0xA63123350Acc8F5ee1b1fBd1A6717135e82dBd28" + }, + { + network: "ethereum", + scope: "account", + label: "hardware_wallet", + status: "active", + createdAt: "1602086832986", + address: "0xA63123350Acc8F5ee1b1fBd1A6717135e82dBd28" + } + ] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/approvedAddresses/{network}/request: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Create New Approved Address + operationId: createNewApprovedAddress + description: | + Allows for creation of an approved withdrawal address. Once the request is made, the 7 day waiting period will begin. Please note that all approved address requests are subject to the 7 day waiting period. + + If you add an address using an account-scoped API key, then the address will be added to your account specific approved address list. If you use a master-scoped API key, the address will be added to your group-level approved address list unless you specify an account. + + This endpoint is subject to additional security constraints and is only accessible via API keys which have configured Trusted IP controls. + + Please reach out to trading@gemini.com if you have any questions about approved addresses. + + ### Roles + This API requires the FundManager role. See [Roles](/roles#roles) for more information. + + parameters: + - $ref: '#/components/parameters/networkParam' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - address + - label + properties: + request: + type: string + description: The literal string "/v1/approvedAddresses/:network/request" where `:network` can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + nonce: + $ref: '#/components/schemas/Nonce' + address: + type: string + description: A string of the address to be added to the approved address list. + label: + type: string + description: The label of the approved address. + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to add the approved address. + memo: + type: string + description: it would be present if applicable, it will be present for cosmos address. + example: + request: "/v1/approvedAddresses/ethereum/request" + nonce: + address: "0x0000000000000000000000000000000000000000" + label: api_added_ETH_address + account: primary + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApprovedAddressMessage' + example: + message: "Approved address addition is now waiting a 7-day approval hold before activation." + + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/approvedAddresses/{network}/remove: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Remove Approved Address + operationId: removeApprovedAddress + description: | + Allows for removal of active or time-pending addresses from the Approved Address list. Addresses that are pending approval from another user on the account cannot be removed via API. + + ### Roles + This API requires the FundManager role. See [Roles](/roles#roles) for more information. + + parameters: + - $ref: '#/components/parameters/networkParam' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - address + properties: + request: + type: string + description: The literal string "/v1/approvedAddresses/:network/remove" where `:network` can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + nonce: + $ref: '#/components/schemas/Nonce' + address: + type: string + description: A string of the address to be removed from the approved address list. + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to remove the approved address. + example: + request: "/v1/approvedAddresses/ethereum/remove" + nonce: + address: "0x0000000000000000000000000000000000000000" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApprovedAddressMessage' + example: + message: "0x0000000000000000000000000000000000000000 removed from group pending-time approved addresses." + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/account/create: + post: + x-zudoku-playground-enabled: false + tags: + - Account Administration + summary: Create New Account + operationId: createNewAccount + description: | + A Master API key can create a new exchange account within the group. This API will return the name of your new account for use with the account parameter in when using Master API keys to perform account level functions. Please see the [example](/account-admin-endpoints#using-master-api-keys). + + ### Roles + The API key you use to access this endpoint must be a Master level key and have the Administrator role assigned. See [Roles](/roles#roles) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - name + properties: + request: + type: string + description: The literal string "/v1/account/create" + nonce: + $ref: '#/components/schemas/Nonce' + name: + type: string + description: A unique name for the new account + type: + type: string + description: Either `exchange` or `custody` is accepted. Will generate an exchange account if `exchange` or parameter is missing. Will generate a custody account if `custody`. + examples: + createAccount: + summary: Create Account Example + description: JSON payload to create a new account + value: + request: "/v1/account/create" + nonce: + name: "My Secondary Account" + type: "exchange" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + account: + type: string + description: Account reference string for use in APIs based off the provided `name` field + type: + type: string + description: Will return the type of account generated. `exchange` if an exchange account was created, `custody` if a custody account was created + example: + account: "my-secondary-account" + type: "exchange" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/account/rename: + post: + x-zudoku-playground-enabled: false + tags: + - Account Administration + summary: Rename Account + operationId: renameAccount + description: | + A Master or Account level API key can rename an account within the group. + + ### Roles + The API key you use to access this endpoint can be either a Master or Account level API key and must have the Administrator role assigned. See [Roles](/roles#roles) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/account/rename". + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: Only required when using a master api-key. The shortname of the account within the subaccount group. Master API keys can get all account shortnames from the `account` field returned by the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + newName: + type: string + description: A unique name for the new account. If not provided, name will not change. + newAccount: + type: string + description: A unique shortname for the new account. If not provided, shortname will not change. + examples: + renameAccount: + summary: Rename Account Example + description: JSON payload to rename an account + value: + request: "/v1/account/rename" + nonce: + account: "my-exchange-account" + newName: "My Exchange Account New Name" + newAccount: "my-exchange-account-new-name" + responses: + '200': + description: An element containing the updated name of the account. + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: New name for the account based off the provided `newName` field. Only returned if `newName` was provided in the request. + account: + type: string + description: New shortname for the account based off the provided `newAccount` field. Only returned if `newAccount` was provided in the request. + example: + name: "My Exchange Account New Name" + account: "my-exchange-account-new-name" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/account/list: + post: + x-zudoku-playground-enabled: false + tags: + - Account Administration + summary: List Accounts in Group + operationId: listAccountsInGroup + description: | + A Master API key can be used to get the accounts within the group. A maximum of 500 accounts can be listed in a single API call. + + ### Roles + The API key you use to access this endpoint must be a Master level key. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `account:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/account/list" + nonce: + $ref: '#/components/schemas/Nonce' + limit_accounts: + type: integer + description: The maximum number of accounts to return. Maximum and default values are both 500. + timestamp: + $ref: '#/components/schemas/TimestampType' + description: Only return accounts created on or before the supplied timestamp. If not provided, the 500 most recently created accounts are returned. + example: + request: "/v1/account/list" + nonce: + limit_accounts: 100 + timestamp: 1632485834721 + responses: + '200': + description: The response will be a JSON object containing all accounts within the master group + content: + application/json: + schema: + type: array + items: + type: object + properties: + name: + type: string + description: The name of the account provided upon creation + account: + type: string + description: Nickname of the specific account (will take the name given, remove all symbols, replace all " " with "-" and make letters lowercase) + type: + type: string + description: Either "exchange" or "custody" depending on type of account + counterparty_id: + type: string + description: The Gemini clearing counterparty ID associated with the API key making the request. Will return `None` for custody accounts + created: + $ref: '#/components/schemas/TimestampType' + description: The timestamp of account creation, displayed as number of milliseconds since 1970-01-01 UTC. This will be transmitted as a JSON number + status: + type: string + description: Either "open" or "closed" + example: + - name: "Primary" + account: "primary" + type: "exchange" + counterparty_id: "EMONNYXH" + created: 1495127793000 + status: "open" + - name: "My Custody Account" + account: "my-custody-account" + type: "custody" + counterparty_id: null + created: 1565970772000 + status: "open" + - name: "Other exchange account!" + account: "other-exchange-account" + type: "exchange" + counterparty_id: "EMONNYXK" + created: 1565970772000 + status: "closed" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/account/transfer/{currency}: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Transfer Between Accounts + operationId: transferBetweenAccounts + description: | + This API allows you to execute an internal transfer between any two accounts within your Master Group. In the scenario of exchange account to exchange account there will be no activity on a blockchain network. All other combinations will result in a movement of funds on a blockchain network. + + Gemini Custody account withdrawals will not occur until the daily custody run occurs. In the case of funds moving from a Gemini Custody account to a Gemini Exchange account, the exchange account will get a precredit for the amount to be received. The exchange account will be able to trade these funds but will be unable to withdraw until the funds are processed on the blockchain and received. + + Gemini Custody accounts request withdrawals to approved addresses in all cases and require the request to come from an approved IP address. Please reach out to trading@gemini.com to enable API withdrawals for custody accounts. + + Gemini Custody accounts do not support fiat currency transfers. + + Fiat transfers between non-derivative and derivatives accounts are prohibited. + + ### Roles + The API key you use to access this endpoint must be a Master level key and have the Fund Manager role assigned. See [Roles](/roles#roles) for more information. + + parameters: + - $ref: '#/components/parameters/currencyParam' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - sourceAccount + - targetAccount + - amount + properties: + request: + type: string + description: The string `/v1/account/transfer/:currency` where `:currency` is replaced with either `usd` or a supported crypto-currency, e.g. `gusd`, `btc`, `eth`, `aave`, etc. See [Symbols and minimums](/market-data/symbols-and-minimums). + nonce: + $ref: '#/components/schemas/Nonce' + sourceAccount: + type: string + description: Nickname of the account you are transferring from. Use the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group) to get all account names in the group. + targetAccount: + type: string + description: Nickname of the account you are transferring to. Use the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group) to get all account names in the group. + amount: + type: string + description: Quoted decimal amount to withdraw + clientTransferId: + type: string + description: A unique identifier for the internal transfer, in uuid4 format + withdrawalId: + type: string + description: Unique ID of the requested withdrawal. + examples: + basicTransfer: + summary: Basic Transfer + description: JSON payload for a basic internal transfer + value: + request: "/v1/account/transfer/btc" + nonce: + sourceAccount: "primary" + targetAccount: "my-secondary-account" + amount: "1.0" + withClientId: + summary: With Client Transfer ID + description: Transfer with a client-supplied identifier + value: + request: "/v1/account/transfer/eth" + nonce: + sourceAccount: "primary" + targetAccount: "my-custody-account" + amount: "1" + clientTransferId: "AA97B177-9383-4934-8543-0F91A7A02838" + responses: + '200': + description: JSON response + content: + application/json: + schema: + type: object + properties: + fromAccount: + type: string + description: Source account where funds are sent from + toAccount: + type: string + description: Target account to receive funds in the internal transfer + amount: + type: string + description: Quantity of assets being transferred + fee: + type: string + description: Fee taken for the transfer. Exchange account to exchange account transfers will always be free and will not be deducted from the free monthly transfer amount for that account. + currency: + type: string + description: Display Name. Can be `Bitcoin`, `Ether`, `Zcash`, `Litecoin`, `Dollar`, etc. + withdrawalId: + type: string + description: _Excludes_ exchange to exchange. Unique ID of the requested withdrawal + uuid: + type: string + description: _Only_ for exchange to exchange. Unique ID of the completed transfer + message: + type: string + description: Message describing result of withdrawal. Will inform of success, failure, or pending blockchain transaction. + txHash: + type: string + description: _Only for Ethereum network transfers. Excludes exchange to exchange transfers_. Transaction hash for ethereum network transfer. + example: + "fromAccount": my-account + "toAccount": my-other-account + "amount": "1" + "currency": Bitcoin + "uuid": "9c153d64-83ba-4532-a159-ebe3f6797766" + "message": Success, transfer completed. + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/transactions: + post: + x-zudoku-playground-enabled: false + tags: + - Fund Management + summary: Get Transaction History + operationId: getTransactionHistory + description: | + + + This endpoint shows trade detail and transactions. There is a `continuation_token` that is a pagination token used for subsequent requests. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned and have the master account scope. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `history:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/transactions" + nonce: + $ref: '#/components/schemas/Nonce' + timestamp_nanos: + description: Only return transfers on or after this timestamp in nanos. If this is defined, do not define “continuation_token”. + allOf: + - $ref: '#/components/schemas/TimestampType' + limit: + type: integer + description: The maximum number of transfers to return. The default is 100 and the maximum is 300. + default: 100 + continuation_token: + type: string + description: For subsequent requests, use the returned `continuation_token` value for next page. If this is defined, do not define “timestamp_nanos”. + example: + request: "/v1/transactions" + nonce: + timestamp_nanos: 1630382206000000000 + limit: 50 + continuation_token: "daccgrp_123421:n712621873886999872349872349:a71289723498273492374978424:m2:iForward" + responses: + '200': + description: The response will be an array of JSON objects, sorted by trade and transfer as well as a continuationToken to be used in subsequent requests. + content: + application/json: + schema: + type: object + properties: + results: + type: array + description: Results will contain either a list of Trade or Transfer responses + items: + $ref: '#/components/schemas/Transaction' + examples: + tradeResponse: + summary: Trade Response + description: Trade Response + value: + results: + - account: primary + amount: "0.001" + clientOrderId: "" + price: "1730.95" + timestampms: 1659201465069 + side: SIDE_TYPE_BUY + isAggressor: true + feeAssetCode: ETH + feeAmount: "0.000000000000000605" + orderId: 73716687406755680 + exchange: gemini + isAuctionFill: false + isClearingFill: false + symbol: ETHUSD + tid: 144115199446910513 + type: trade + - account: primary + amount: "0.001" + clientOrderId: "" + price: "1679.02" + timestampms: 1659201465222 + side: SIDE_TYPE_SELL + isAggressor: true + feeAssetCode: ETH + feeAmount: "0.00000000000000000587" + orderId: 73716687406755680 + exchange: gemini + isAuctionFill: false + isClearingFill: false + symbol: ETHUSD + tid: 144115199446910494 + type: trade + continuationToken: "daccgrp_1500611:n7126218738869976937315434496:a7126216029949884380085223424:m2:iForward" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + + /v1/oauth/revokeByToken: + post: + x-zudoku-playground-enabled: false + tags: + - OAuth + summary: Revoke OAuth Token + operationId: revokeOAuthToken + description: | + The `access_token` may be revoked at any time by using `v1/oauth/revokeByToken`. Once a token is revoked or expires, it can no longer be used to make requests. + + This endpoint is only available using an `access_token` and will revoke the token used to make the request. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + properties: + request: + type: string + description: The literal string "/v1/oauth/revokeByToken" + examples: + revokeToken: + summary: Revoke Token Request + description: JSON payload to revoke an OAuth token + value: + request: "/v1/oauth/revokeByToken" + + responses: + '200': + description: An object that indicates the access_token has been revoked. + content: + application/json: + schema: + type: object + properties: + message: + type: string + description: A message that indicates the token has been revoked for the account + examples: + revokeTokenResponse: + summary: Revoke Token Response + description: JSON response for a successful token revocation + value: + message: "OAuth tokens and codes have been revoked for 00000000-0000-0000-0000-000000000000 on your account." + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/balances/staking: + post: + x-zudoku-playground-enabled: false + tags: + - Staking + summary: List Staking Balances + operationId: listStakingBalances + description: | + This will show the available balance in Staking as well as the available balance for withdrawal. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/balances/staking" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group." + example: + request: "/v1/balances/staking" + nonce: + account: primary + responses: + '200': + description: The staking balances + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/StakingBalance' + example: + - type: "Staking" + currency: "MATIC" + balance: 10 + available: 0 + availableForWithdrawal: 10 + balanceByProvider: + "62b21e17-2534-4b9f-afcf-b7edb609dd8d": + balance: 10 + - type: "Staking" + currency: "ETH" + balance: 3 + available: 0 + availableForWithdrawal: 3 + balanceByProvider: + "62b21e17-2534-4b9f-afcf-b7edb609dd8d": + balance: 3 + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/staking/stake: + post: + x-zudoku-playground-enabled: false + tags: + - Staking + summary: Stake Crypto Funds + operationId: stakeCryptoFunds + description: | + Initiates Staking deposits. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Trader role assigned. See [Roles](/roles#roles) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - providerId + - currency + - amount + properties: + request: + type: string + description: The literal string "v1/staking/stake" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group." + providerId: + type: string + description: Provider Id, in uuid4 format. providerId is accessible from the [Staking rates](#list-staking-rates) response + currency: + type: string + description: Currency code, see [symbols](/market-data/symbols-and-minimums) + amount: + type: string + format: decimal + description: The amount of currency to deposit + example: + request: "v1/staking/stake" + nonce: + providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: "MATIC" + amount: 30 + responses: + '200': + description: The staking deposit transaction + content: + application/json: + schema: + $ref: '#/components/schemas/StakingDeposit' + example: + transactionId: "65QN4XM5" + providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: "MATIC" + amount: 30 + rates: + rate: 540 + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/staking/history: + post: + x-zudoku-playground-enabled: false + tags: + - Staking + summary: List Staking Event History + operationId: listStakingEventHistory + description: | + This will show all staking deposits, redemptions and interest accruals. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + + ### How to iterate through all transactions: + To retrieve your full Staking history walking backwards, + + 1. Initial request: `POST` to https://api.gemini.com/v1/staking/history with a JSON payload including `sortAsc` set to `false` and a limit key with value `500`. + 2. When you receive the list of Staking transactions, they will be sorted by `datetime` descending - so the last element in the list will have the lowest `timestamp` value. For this example, say that value is `X`. + 3. Create a second `POST` request with a JSON payload including a `until` timestamp key with value `X-1`, `sortAsc` set to `false`, and a limit key with value `500`. + 4. Take the last element of the list returned with lowest `datetime` value `Y` and create a third `POST` request with a JSON payload including a `until` timestamp key with value `Y-1`, `sortAsc` set to false, and a `limit` key with value `500`. + 5. Continue creating `POST` requests and retrieving Staking transactions until an empty list is returned. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/staking/history" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group." + since: + description: "In iso datetime with timezone format. Defaults to the timestamp of the first deposit into Staking." + allOf: + - $ref: '#/components/schemas/TimestampType' + until: + description: "In iso datetime with timezone format, default to current time as of server time" + allOf: + - $ref: '#/components/schemas/TimestampType' + limit: + type: integer + description: "The maximum number of transactions to return. Default is 50, max is 500." + default: 50 + providerId: + type: string + description: "Borrower Id, in uuid4 format. providerId is accessible from the [Staking rates](#list-staking-rates) response" + currency: + type: string + description: "Currency code, see [symbols](/market-data/symbols-and-minimums)" + interestOnly: + type: boolean + description: "Toggles whether to only return daily interest transactions. Defaults to false." + default: false + sortAsc: + type: boolean + description: "Toggles whether to sort the transactions in ascending order by datetime. Defaults to false." + default: false + example: + request: "/v1/staking/history" + nonce: + account: primary + since: "2022-11-01T00:00:00.000Z" + until: "2022-11-03T00:00:00.000Z" + limit: 50 + responses: + '200': + description: Staking transaction history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/StakingHistory' + example: + - providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + transactions: + - transactionId: "MPZ7LDD8" + transactionType: "Redeem" + amountCurrency: "MATIC" + amount: 20 + dateTime: 1667418560153 + - transactionId: "65QN4XM5" + transactionType: "Deposit" + amountCurrency: "MATIC" + amount: 30 + dateTime: 1667418287795 + - transactionId: "YP22OK4P" + transactionType: "Deposit" + amountCurrency: "ETH" + amount: 3 + dateTime: 1667397368929 + - transactionId: "TQN9OPN" + transactionType: "Interest" + amountCurrency: "MATIC" + amount: 0.01 + priceCurrency: "USD" + priceAmount: 0.1 + dateTime: 1667418287795 + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/staking/rates: + get: + tags: + - Staking + summary: List Staking Rates + operationId: listStakingRates + description: | + This will return the current Gemini Staking interest rates (in bps). When including the specific asset(s) in the request, the response will include the specific assets' (e.g. `eth`, `matic`) Staking rate. When not including the specific asset in the request, the response will include all Staking rates. + responses: + '200': + description: JSON response with staking rates + content: + application/json: + schema: + $ref: '#/components/schemas/StakingRateResponse' + example: + "62bb4d27-a9c8-4493-a737-d4fa33994f1f": + MATIC: + providerId: "62bb4d27-a9c8-4493-a737-d4fa33994f1f" + rate: 95.8909 + apyPct: 0.96 + ratePct: 0.958909 + depositUsdLimit: 500000 + ETH: + providerId: "62bb4d27-a9c8-4493-a737-d4fa33994f1f" + rate: 228.0197 + apyPct: 2.31 + ratePct: 2.280197 + depositUsdLimit: 500000 + SOL: + providerId: "62bb4d27-a9c8-4493-a737-d4fa33994f1f" + rate: 321.5282 + apyPct: 3.27 + ratePct: 3.215282 + depositUsdLimit: 500000 + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/staking/rewards: + post: + x-zudoku-playground-enabled: false + tags: + - Staking + summary: List Staking Rewards + operationId: listStakingRewards + description: | + This will show the historical Staking reward payments and accrual. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Auditor role assigned. See [Roles](/roles#roles) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - since + properties: + request: + type: string + description: The literal string "/v1/staking/rewards" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group." + since: + type: string + description: In iso datetime with timezone format + until: + type: string + description: "In iso datetime with timezone format, default to current time as of server time" + providerId: + type: string + description: "Borrower Id, in uuid4 format. providerId is accessible from the [Staking rates](#list-staking-rates) response" + currency: + type: string + description: "Currency code, see [symbols](/market-data/symbols-and-minimums)" + example: + request: "/v1/staking/rewards" + nonce: + since: "2022-08-20T00:00:00.000Z" + until: "2022-11-05T00:00:00.000Z" + providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: "ETH" + responses: + '200': + description: A nested JSON object, organized by provider, then currency + content: + application/json: + schema: + $ref: '#/components/schemas/StakingRewardsResponse' + example: + "62b21e17-2534-4b9f-afcf-b7edb609dd8d": + MATIC: + providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: "MATIC" + accrualTotal: 0.103994 + ratePeriods: + - providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: "MATIC" + apyPct: 5.75 + ratePct: 5.592369 + numberOfAccruals: 1 + accrualTotal: 0.0065678 + firstAccrualAt: "2022-08-23T20:00:00.000Z" + lastAccrualAt: "2022-08-23T20:00:00.000Z" + - providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: "MATIC" + apyPct: 5.2 + ratePct: 5.073801 + numberOfAccruals: 1 + accrualTotal: 0.0037971687995651837 + firstAccrualAt: "2022-10-28T20:00:00.000Z" + lastAccrualAt: "2022-10-28T20:00:00.000Z" + ETH: + providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: "ETH" + accrualTotal: 0.017999076209977 + ratePeriods: + - providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: "ETH" + apyPct: 0.66 + ratePct: 0.65913408 + numberOfAccruals: 1 + accrualTotal: 0.00014802170517505 + firstAccrualAt: "2022-11-02T20:00:00.000Z" + lastAccrualAt: "2022-11-02T20:00:00.000Z" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/staking/unstake: + post: + x-zudoku-playground-enabled: false + tags: + - Staking + summary: Unstake Crypto Funds + operationId: unstakeCryptoFunds + description: | + Initiates Staking withdrawals. + + ### Roles + The API key you use to access this endpoint must have the Trader, Fund Manager or Trader role assigned. See [Roles](/roles#roles) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - providerId + - currency + - amount + properties: + request: + type: string + description: The literal string "v1/staking/unstake" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group." + providerId: + type: string + description: Provider Id, in uuid4 format. providerId is accessible from the [Staking rates](#list-staking-rates) response + currency: + type: string + description: Currency code, see [symbols](/market-data/symbols-and-minimums) + amount: + type: string + format: decimal + description: The amount of currency to withdraw + example: + request: "v1/staking/unstake" + nonce: + providerId: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: "MATIC" + amount: 20 + responses: + '200': + description: The staking withdrawal transaction + content: + application/json: + schema: + $ref: '#/components/schemas/StakingWithdrawal' + example: + transactionId: "MPZ7LDD8" + amount: 20 + amountPaidSoFar: 20 + amountRemaining: 0 + currency: "MATIC" + requestInitiated: "2022-11-02T19:49:20.153Z" + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/roles: + post: + x-zudoku-playground-enabled: false + tags: + - Account Administration + summary: Roles Endpoint + operationId: getRoles + description: | + The `v1/roles` endpoint will return a string of the role of the current API key. The response fields will be different for account-level and master-level API keys. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/roles" + example: /v1/roles + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + example: + request: "/v1/roles" + nonce: + responses: + '200': + description: The response will be a JSON object indicating the assigned roles to the set of API keys used to call `/v1/roles`. The `Auditor` role cannot be combined with other roles. `Fund Manager` and `Trader` can be combined. + content: + application/json: + schema: + $ref: '#/components/schemas/RoleResponse' + examples: + accountLevel: + summary: Account-scoped key + description: Successful response for account-scoped key + value: + isAuditor: false + isFundManager: true + isTrader: true + masterLevel: + summary: Master-scoped key + description: Successful response for master-scoped key + value: + counterparty_id: "EMONNYXJ" + isAuditor: false + isFundManager: true + isTrader: true + isAccountAdmin: true + + /v1/margin: + post: + x-zudoku-playground-enabled: false + tags: + - Derivatives + summary: Get Account Margin + operationId: getAccountMargin + description: | + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See Roles for more information. + + The OAuth scope must have `orders:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + - symbol + properties: + request: + type: string + description: The API endpoint path + example: /v1/margin + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + example: primary + symbol: + type: string + description: Trading pair symbol. See [symbols and minimums](/market-data/symbols-and-minimums) + example: + request: "/v1/margin" + nonce: + symbol: "BTC-GUSD-PERP" + responses: + '200': + description: JSON object + content: + application/json: + schema: + $ref: '#/components/schemas/MarginResponse' + example: + margin_assets_value: "9800" + initial_margin: "6000" + available_margin: "3800" + margin_maintenance_limit: "5800" + leverage: "12.34567" + notional_value: "1300" + estimated_liquidation_price: "1300" + initial_margin_positions: "3500" + reserved_margin: "2500" + reserved_margin_buys: "1800" + reserved_margin_sells: "700" + buying_power: "0.19" + selling_power: "0.19" + + /v1/perpetuals/fundingPayment: + post: + x-zudoku-playground-enabled: false + tags: + - Derivatives + summary: List Funding Payments + operationId: listFundingPayments + description: | + + + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See Roles for more information. + + The OAuth scope must have `orders:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - name: since + in: query + description: If specified, only return funding payments after this point. Default value is 24h in past. See [**Timestamps**](/rest/~schemas#timestamp-type) for more information + required: false + schema: + $ref: '#/components/schemas/TimestampType' + - name: to + in: query + description: If specified, only returns funding payment until this point. Default value is now. See [**Timestamps**](/rest/~schemas#timestamp-type) for more information + required: false + schema: + $ref: '#/components/schemas/TimestampType' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The API endpoint path + example: /v1/perpetuals/fundingPayment + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + example: primary + example: + request: "/v1/perpetuals/fundingPayment" + nonce: + responses: + '200': + description: The response will be an array of funding payment objects. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FundingPayment' + example: + - eventType: "Hourly Funding Transfer" + hourlyFundingTransfer: + eventType: "Hourly Funding Transfer" + timestamp: 1683730803940 + assetCode: "GUSD" + action: "Debit" + quantity: + currency: "GUSD" + value: "4.78958" + - eventType: "Hourly Funding Transfer" + hourlyFundingTransfer: + eventType: "Hourly Funding Transfer" + timestamp: 1683734406746 + assetCode: "GUSD" + action: "Debit" + quantity: + currency: "GUSD" + value: "4.78958" + instrumentSymbol: "BTCGUSDPERP" + + /v1/perpetuals/fundingpaymentreport/records.xlsx: + get: + x-zudoku-playground-enabled: false + tags: + - Derivatives + summary: Get Funding Payment Report File + operationId: getFundingPaymentReportFile + description: | + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See Roles for more information. + + The OAuth scope must have `orders:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + + ### Examples + - `&fromDate=2024-04-10&toDate=2024-04-25&numRows=1000`
+ Compare and obtain the minimum records between (2024-04-10 to 2024-04-25) and 1000. If (2024-04-10 to 2024-04-25) contains 360 records. Then fetch the minimum between 360 and 1000 records only. + + - `&numRows=2024-04-10&toDate=2024-04-25`
+ If (2024-04-10 to 2024-04-25) contains 360 records. Then fetch 360 records only. + + - `&numRows=1000`
+ Fetch maximum 1000 records starting from Now to a historical date + + - ``
+ Fetch maximum 8760 records starting from Now to a historical date + parameters: + - name: fromDate + in: query + description: If empty, will only fetch records by numRows value. + required: false + schema: + type: string + format: date + - name: toDate + in: query + description: If empty, will only fetch records by numRows value. + required: false + schema: + type: string + format: date + - name: numRows + in: query + description: If empty, default value '8760' + required: false + schema: + type: integer + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: false + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The API endpoint path + example: /v1/perpetuals/fundingpaymentreport/records.xlsx + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + example: primary + example: + request: "/v1/perpetuals/fundingpaymentreport/records.xlsx?fromDate=2024-04-10&toDate=2024-04-25&numRows=1000" + nonce: + responses: + '200': + description: XLSX file downloaded containing funding payment report. + headers: + Content-Disposition: + schema: + type: string + example: attachment; filename=FundingPayment_Report.xlsx + content: + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: + schema: + type: string + format: binary + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/perpetuals/fundingpaymentreport/records.json: + post: + x-zudoku-playground-enabled: false + tags: + - Derivatives + summary: Get Funding Payment Report JSON + operationId: getFundingPaymentReportJson + description: | + This endpoint retrieves funding payment report in JSON format. + + ### Examples + - `&fromDate=2024-04-10&toDate=2024-04-25&numRows=1000`
+ Compare and obtain the minimum records between (2024-04-10 to 2024-04-25) and 1000. If (2024-04-10 to 2024-04-25) contains 360 records. Then fetch the minimum between 360 and 1000 records only. + + - `&numRows=2024-04-10&toDate=2024-04-25`
+ If (2024-04-10 to 2024-04-25) contains 360 records. Then fetch 360 records only. + + - `&numRows=1000`
+ Fetch maximum 1000 records starting from Now to a historical date + + - ``
+ Fetch maximum 8760 records starting from Now to a historical date + parameters: + - name: fromDate + in: query + description: If empty, will only fetch records by numRows value. + required: false + schema: + type: string + format: date + - name: toDate + in: query + description: If empty, will only fetch records by numRows value. + required: false + schema: + type: string + format: date + - name: numRows + in: query + description: If empty, default value '8760' + required: false + schema: + type: integer + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The API endpoint path + example: /v1/perpetuals/fundingpaymentreport/records.json?fromDate=2024-04-10&toDate=2024-04-25&numRows=1000 + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + example: primary + example: + request: "/v1/perpetuals/fundingpaymentreport/records.json?fromDate=2024-04-10&toDate=2024-04-25&numRows=1000" + nonce: + responses: + '200': + description: JSON response containing funding payment report. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FundingPaymentReportItem' + example: + - eventType: "Hourly Funding Transfer" + timestamp: 1713344403617 + assetCode: "GUSD" + action: "Credit" + quantity: + currency: "GUSD" + value: "35.81084" + instrumentSymbol: "BTCGUSDPERP" + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/positions: + post: + x-zudoku-playground-enabled: false + tags: + - Derivatives + summary: Get Open Positions + operationId: getOpenPositions + description: | + ### Roles + The API key you use to access this endpoint must have the Trader or Auditor role assigned. See [Roles](/roles#roles) for more information. + + The OAuth scope must have `orders:read` assigned to access this endpoint. See [OAuth Scopes](/authentication/oauth#oauth-scopes) for more information. + parameters: + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/positions" + nonce: + $ref: '#/components/schemas/Nonce' + account: + type: string + description: Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which the orders were placed. Only available for exchange accounts. + example: + request: "/v1/positions" + nonce: + account: "primary" + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + openPositions: + type: array + items: + $ref: '#/components/schemas/OpenPosition' + example: [ + { + symbol: btcgusdperp, + instrument_type: perp, + quantity: "0.2", + notional_value: "4000.036", + realised_pnl: "1234.5678", + unrealised_pnl: "999.946", + average_cost: "15000.45", + mark_price: "20000.18" + } + ] + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v1/riskstats/{symbol}: + get: + tags: + - Derivatives + summary: Get Risk Stats + operationId: getRiskStats + parameters: + - name: symbol + in: path + required: true + schema: + type: string + description: | + Perps Trading pair symbol

+ + `BTCGUSDPERP`, etc. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols). + responses: + '200': + description: The response will be an json object + content: + application/json: + schema: + $ref: '#/components/schemas/RiskStatsResponse' + example: { + product_type: PerpetualSwapContract, + mark_price: "30080.00", + index_price: "30079.046", + open_interest: "14.439", + open_interest_notional: "434325.12" + } + + /v2/ticker/{symbol}: + get: + tags: + - Market Data + summary: Get Ticker V2 + operationId: getTickerV2 + description: This endpoint retrieves information about recent trading activity for the provided symbol. + parameters: + - name: symbol + in: path + required: true + schema: + type: string + description: Trading pair symbol + example: BTCUSD + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/TickerInfo' + example: + symbol: "BTCUSD" + open: "9121.76" + high: "9440.66" + low: "9106.51" + close: "9347.66" + changes: [ + "9365.1", + "9386.16", + "9373.41", + "9322.56", + "9268.89", + "9265.38", + "9245", + "9231.43", + "9235.88", + "9265.8", + "9295.18", + "9295.47", + "9310.82", + "9335.38", + "9344.03", + "9261.09", + "9265.18", + "9282.65", + "9260.01", + "9225", + "9159.5", + "9150.81", + "9118.6", + "9148.01" + ] + bid: "9345.70" + ask: "9347.67" + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v2/candles/{symbol}/{time_frame}: + get: + tags: + - Market Data + summary: List Candles + operationId: listCandles + description: This endpoint retrieves time-intervaled data for the provided symbol. + parameters: + - name: symbol + in: path + required: true + schema: + type: string + description: Trading pair symbol + example: BTCUSD + - name: time_frame + in: path + required: true + schema: + type: string + enum: [1m, 5m, 15m, 30m, 1h, 6h, 1d] + description: | + Time range for each candle: + * `1m` - 1 minute + * `5m` - 5 minutes + * `15m` - 15 minutes + * `30m` - 30 minutes + * `1h` - 1 hour + * `6h` - 6 hours + * `1day` - 1 day + example: 15m + responses: + '200': + description: The response will be an array of arrays + content: + application/json: + schema: + $ref: '#/components/schemas/CandleResponse' + example: [ + [ + 1559755800000, + 7781.6, + 7820.23, + 7776.56, + 7819.39, + 34.7624802159 + ], + [ + 1559755800000, + 7781.6, + 7829.46, + 7776.56, + 7817.28, + 43.4228281059 + ] + ] + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v2/derivatives/candles/{symbol}/{time_frame}: + get: + tags: + - Market Data + summary: List Derivative Candles + operationId: listDerivativeCandles + description: This endpoint retrieves time-intervaled data for the provided perpetual symbol. + parameters: + - name: symbol + in: path + required: true + schema: + type: string + description: "Trading pair symbol. Available only for perpetual pairs like `BTCGUSDPERP`" + example: BTCGUSDPERP + - name: time_frame + in: path + required: true + schema: + type: string + enum: [1m] + description: "Time range for each candle. `1m`: 1 minute (only)" + example: 1m + responses: + '200': + description: The response will be an array of arrays + content: + application/json: + schema: + $ref: '#/components/schemas/CandleResponse' + example: [ + [ + 1714126740000, + 68038, + 68038, + 68038, + 68038, + 0 + ], + [ + 1714126680000, + 68038, + 68038, + 68038, + 68038, + 0 + ] + ] + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + + /v2/fxrate/{symbol}/{timestamp}: + get: + tags: + - Market Data + summary: FX Rate + operationId: getFXRate + description: | + We have a growing international institutional customer base. When pulling market data for charting, it can be useful to have access to our FX rate for the relevant currency at that time. + + Please note, Gemini does not offer foreign exchange services. This endpoint is for historical reference only and does not provide any guarantee of future exchange rates. + + **Roles** + The API key you use to access this endpoint must have the Auditor role assigned. See Roles for more information. + + **Supported Pairs** + + ` + [AUDUSD, CADUSD, COPUSD, EURUSD, CHFUSD, HKDUSD, NZDUSD, GBPUSD, BRLUSD, INRUSD, SGDUSD, KRWUSD, JPYUSD, CNYUSD] + ` + parameters: + - $ref: '#/components/parameters/symbolParam' + - $ref: '#/components/parameters/timestampParam' + - $ref: '#/components/parameters/apiKeyAuth' + - $ref: '#/components/parameters/signatureAuth' + - $ref: '#/components/parameters/payloadAuth' + - $ref: '#/components/parameters/contentType' + - $ref: '#/components/parameters/contentLength' + - $ref: '#/components/parameters/cacheControl' + + + security: + - apiKeyAuth: [] + signatureAuth: [] + payloadAuth: [] + + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/FxRate' + example: + fxPair: AUDUSD + rate: "0.69" + asOf: 1594651859000 + provider: bcb + benchmark: Spot + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/ApiKeyIpFilteringFailure' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + +components: + securitySchemes: + apiKeyAuth: + type: apiKey + in: header + name: X-GEMINI-APIKEY + description: Your API key + payloadAuth: + type: apiKey + in: header + name: X-GEMINI-PAYLOAD + description: Base64-encoded JSON payload + signatureAuth: + type: apiKey + in: header + name: X-GEMINI-SIGNATURE + description: HEX-encoded HMAC-SHA384 of payload signed with API secret + + schemas: + # Custom Data types + TimestampType: + description: timestamp + oneOf: + - type: string + description: | + Gemini strongly recommends using milliseconds instead of seconds for timestamps. + + | Timestamp format | Example | Supported request type | + |-----------------------|-----------------------|------------------------| + | string (seconds) | `1495127793` | `POST` only | + | string (milliseconds) | `1495127793000` | `POST` only | + example: "1495127793000" + - type: integer + format: int64 + description: | + Gemini strongly recommends using milliseconds instead of seconds for timestamps. + + | Timestamp format | Example | Supported request type | + |-----------------------------|---------------------------|------------------------| + | whole number (seconds) | `1495127793` | `GET`, `POST` | + | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | + example: 1495127793000 + Nonce: + oneOf: + - type: TimestampType + $ref: '#/components/schemas/TimestampType' + example: 1495127793000 + - type: integer + example: 1495127793000 + description: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + + # Common schema components + ErrorResponse: + type: object + properties: + result: + type: string + description: Error + reason: + type: string + description: A short description + message: + type: string + description: Detailed error message + + SymbolDetails: + type: object + properties: + symbol: + type: string + example: BTCUSD + description: The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + base_currency: + type: string + example: BTC + description: CCY1 or the top currency. (i.e `BTC` in `BTCUSD`) + quote_currency: + type: string + example: USD + description: CCY2 or the quote currency. (i.e `USD` in `BTCUSD`) + tick_size: + type: number + format: decimal + example: 0.00000001 + description: The number of decimal places in the `base_currency`. (i.e `1e-8`) + quote_increment: + type: number + format: decimal + example: 0.01 + description: The number of decimal places in the `quote_currency` (i.e `0.01`) + min_order_size: + type: string + example: "0.00001" + description: The minimum order size in `base_currency` units (i.e `0.00001`) + status: + type: string + example: open + description: Status of the current order book. Can be `open`, `closed`, `cancel_only`, `post_only`, `limit_only`. + wrap_enabled: + type: boolean + example: false + description: | + When `True`, symbol can be wrapped using this endpoint: + `POST https://api.gemini.com/v1/wrap/:symbol` + product_type: + type: string + example: spot + description: Instrument type `spot` / `swap` -- where `swap` signifies `perpetual swap`. + contract_type: + type: string + example: vanilla + description: | + `vanilla` / `linear` / `inverse` where `vanilla` is for spot + while `linear` is for perpetual swap and `inverse` is a special case perpetual swap where the perpetual contract will be settled in base currency. + contract_price_currency: + type: string + example: USD + description: | + CCY2 or the quote currency for spot instrument (i.e. `USD` in `BTCUSD`) + Or collateral currency of the contract in case of perpetual swap instrument. + + Ticker: + type: object + properties: + bid: + type: string + format: decimal + description: The highest bid currently available + example: "977.59" + ask: + type: string + format: decimal + description: The lowest ask currently available + example: "977.35" + last: + type: string + format: decimal + description: The price of the last executed trade + example: "977.65" + volume: + type: object + description: Information about the 24 hour volume on the exchange. See properties below + properties: + timestamp: + $ref: '#/components/schemas/TimestampType' + example: 1483018200000 + description: The end of the 24-hour period over which volume was measured. [timestamp (ms)](/rest/~schemas#timestamp-type) + price_symbol: + type: string + format: decimal + description: The volume denominated in the price currency + example: "2210.505328803" + quantity_symbol: + type: string + format: decimal + description: The volume denominated in the quantity currency + example: "2135477.463379586263" + + OrderBook: + type: object + properties: + bids: + type: array + description: The bid price levels currently on the book. These are offers to buy at a given price. + items: + $ref: '#/components/schemas/OrderBookEntry' + asks: + type: array + description: The ask price levels currently on the book. These are offers to sell at a given price. + items: + $ref: '#/components/schemas/OrderBookEntry' + + OrderBookEntry: + type: object + properties: + price: + type: string + format: decimal + description: The price + amount: + type: string + format: decimal + description: The total quantity remaining at the price + timestamp: + type: string + description: "**DO NOT USE** - this field is included for compatibility reasons only and is just populated with a dummy value." + + Trade: + type: object + properties: + timestamp: + $ref: '#/components/schemas/TimestampType' + example: 1547146811 + description: The time that the trade was executed + timestampms: + $ref: '#/components/schemas/TimestampType' + example: 1547146811357 + description: The time that the trade was executed in milliseconds + tid: + type: integer + format: int64 + example: 5335307668 + description: The trade ID number + price: + type: string + format: decimal + example: "3610.85" + description: The price the trade was executed at + amount: + type: string + format: decimal + example: "0.27413495" + description: The amount that was traded + exchange: + type: string + example: gemini + description: Will always be "gemini" + type: + type: string + enum: [buy, sell] + example: buy + description: | + - `buy` means that an ask was removed from the book by an incoming buy order. + - `sell` means that a bid was removed from the book by an incoming sell order. + broken: + type: boolean + example: "false" + description: Whether the trade was broken or not. Broken trades will not be displayed by default; use the `include_breaks` to display them. + + Heartbeat: + type: object + properties: + request: + type: string + description: The literal string `/v1/heartbeat` + nonce: + oneOf: + - type: string + description: | + Gemini strongly recommends using milliseconds instead of seconds for timestamps. + + | Timestamp format | Example | Supported request type | + |-----------------------|-----------------------|------------------------| + | string (seconds) | `'1495127793'` | `POST` only | + | string (milliseconds) | `'1495127793000'` | `POST` only | + - type: integer + format: int64 + description: | + Gemini strongly recommends using milliseconds instead of seconds for timestamps. + + | Timestamp format | Example | Supported request type | + |-----------------------------|---------------------------|------------------------| + | whole number (seconds) | `1495127793` | `GET`, `POST` | + | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | + + description: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + + NewOrderRequest: + type: object + required: + - request + - nonce + - symbol + - amount + - price + - side + - type + + properties: + request: + type: string + description: The literal string "/v1/order/new" + example: /v1/order/new + nonce: + type: number + description: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + client_order_id: + type: string + description: "*Recommended*. A [client-specified order id](/client-order-id)" + symbol: + type: string + description: The [symbol](/market-data/symbols-and-minimums) for the new order + example: BTCUSD + amount: + type: string + description: Quoted decimal amount to purchase + example: "5" + price: + type: string + description: Quoted decimal amount to spend per unit + example: "3633.00" + side: + type: string + enum: [buy, sell] + example: buy + type: + type: string + enum: [exchange limit, exchange stop limit, exchange market] + description: The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. + example: exchange limit + options: + type: array + items: + type: string + enum: [maker-or-cancel, immediate-or-cancel, fill-or-kill] + description: "An optional array containing at most one supported order execution option. See Order execution options for details." + example: ["maker-or-cancel"] + stop_price: + type: string + description: "The price to trigger a stop-limit order. Only available for stop-limit orders." + margin_order: + type: boolean + description: "Set to `true` to place this order on a margin account using borrowed funds. Defaults to `false`. Only available for margin-enabled accounts. See [Margin Trading](/margin/account-summary) for details." + example: false + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + + CancelOrderRequest: + type: object + required: + - request + - nonce + - order_id + properties: + request: + type: string + description: The literal string "/v1/order/cancel" + example: /v1/order/cancel + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + order_id: + type: integer + format: int64 + x-unsigned-int64: true + description: The order ID given by `/order/new` + example: 106817811 + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the order. Only available for exchange accounts." + example: primary + + CancelAllOrdersRequest: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/order/cancel/all" + example: "/v1/order/cancel/all" + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts." + example: primary + + CancelAllOrdersBySessionRequest: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The literal string "/v1/order/cancel/session" + example: "/v1/order/cancel/session" + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts." + example: primary + + OrderStatusRequest: + type: object + required: + - request + - nonce + - order_id + properties: + request: + type: string + description: The API endpoint path + example: /v1/order/status + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + example: primary + order_id: + type: integer + format: int64 + x-unsigned-int64: true + description: The order id to get information on. The `order_id` represents a whole number and is transmitted as an unsigned 64-bit integer in JSON format. `order_id` cannot be used in combination with `client_order_id`. + example: 123456789012345 + client_order_id: + type: string + description: "The `client_order_id` used when placing the order. `client_order_id` cannot be used in combination with `order_id`" + include_trades: + type: boolean + description: "Either `True` or `False`. If `True` the endpoint will return individual trade details of all fills from the order." + + MyTradesRequest: + type: object + required: + - request + - nonce + properties: + request: + type: string + description: The API endpoint path + example: /v1/mytrades + nonce: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + title: The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + account: + type: string + description: "Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts." + example: primary + symbol: + type: string + description: "The [symbol](/market-data/symbols-and-minimums) to retrieve trades for" + example: btcusd + limit_trades: + type: integer + description: "The maximum number of trades to return. Default is 50, max is 500." + example: 50 + timestamp: + $ref: '#/components/schemas/TimestampType' + description: "Only return trades on or after this timestamp. See [Data Types: Timestamps](/rest/~schemas#timestamp-type) for more information. If not present, will show the most recent orders." + example: 1591084414000 + + LimitOrderResponse: + type: object + title: Limit Order Response + properties: + order_id: + type: string + id: + type: string + symbol: + type: string + exchange: + type: string + avg_execution_price: + type: string + side: + type: string + enum: [buy, sell] + type: + type: string + enum: [exchange limit, exchange stop limit, exchange market] + timestamp: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + timestampms: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + is_live: + type: boolean + is_cancelled: + type: boolean + is_hidden: + type: boolean + was_forced: + type: boolean + executed_amount: + type: string + remaining_amount: + type: string + format: double + client_order_id: + type: string + options: + type: array + items: + type: string + price: + type: string + format: double + original_amount: + type: string + format: double + + StopLimitOrderResponse: + type: object + title: Stop-Limit Order Response + properties: + order_id: + type: string + id: + type: string + symbol: + type: string + exchange: + type: string + avg_execution_price: + type: string + side: + type: string + enum: [buy, sell] + type: + type: string + enum: [exchange stop limit] + timestamp: + $ref: '#/components/schemas/TimestampType' + timestampms: + $ref: '#/components/schemas/TimestampType' + is_live: + type: boolean + is_cancelled: + type: boolean + is_hidden: + type: boolean + was_forced: + type: boolean + executed_amount: + type: string + options: + type: array + items: + type: string + stop_price: + type: string + format: double + price: + type: string + format: double + original_amount: + type: string + format: double + + CancelOrderResponse: + type: object + properties: + order_id: + type: string + format: integer + id: + type: string + format: integer + symbol: + type: string + exchange: + type: string + avg_execution_price: + type: string + format: double + side: + type: string + enum: [buy, sell] + type: + type: string + enum: [exchange limit, exchange stop limit, exchange market] + timestamp: + $ref: '#/components/schemas/TimestampType' + timestampms: + $ref: '#/components/schemas/TimestampType' + is_live: + type: boolean + is_cancelled: + type: boolean + is_hidden: + type: boolean + was_forced: + type: boolean + executed_amount: + type: string + format: double + remaining_amount: + type: string + format: double + reason: + type: string + enum: [MakerOrCancelWouldTake, ExceedsPriceLimits, SelfCrossPrevented, ImmediateOrCancelWouldPost, FillOrKillWouldNotFill, Requested, MarketClosed, TradingClosed] + options: + type: array + items: + type: string + price: + type: string + format: double + original_amount: + type: string + format: double + + Order: + type: object + properties: + order_id: + type: string + format: integer + description: The order id + client_order_id: + type: string + format: integer + description: An optional [client-specified order id](/client-order-id#client-order-id) + symbol: + type: string + description: The [symbol](/market-data/symbols-and-minimums#symbols-and-minimums) of the order + exchange: + type: string + description: Will always be "gemini" + price: + type: string + format: decimal + description: The price the order was issued at + avg_execution_price: + type: string + format: decimal + description: The average price at which this order as been executed so far. 0 if the order has not been executed at all. + side: + type: string + enum: [buy, sell] + type: + type: string + enum: [exchange limit, exchange stop limit, exchange market] + description: Description of the order + options: + type: array + items: + type: string + description: An array containing at most one supported order execution option. See [Order execution options](/rest/orders#create-new-order) for details. + timestamp: + $ref: '#/components/schemas/TimestampType' + description: The timestamp the order was submitted. Note that for compatibility reasons, this is returned as a string. We recommend using the timestampms field instead. + timestampms: + $ref: '#/components/schemas/TimestampType' + description: The timestamp the order was submitted in milliseconds. + is_live: + type: boolean + description: "`true` if the order is active on the book (has remaining quantity and has not been canceled)" + is_cancelled: + type: boolean + description: '`true` if the order has been canceled. Note the spelling, "cancelled" instead of "canceled". This is for compatibility reasons.' + reason: + type: string + description: Populated with the reason your order was canceled, if available. + was_forced: + type: boolean + description: Will always be `false`. + executed_amount: + type: string + format: decimal + description: The amount of the order that has been filled. + remaining_amount: + type: string + format: decimal + description: The amount of the order that has not been filled. + original_amount: + type: string + format: decimal + description: The originally submitted amount of the order. + is_hidden: + type: boolean + description: Will always return `false`. + trades: + type: array + items: + type: object + properties: + price: + type: string + format: decimal + description: The price that the execution happened at + amount: + type: string + format: decimal + description: The quantity that was executed + timestamp: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + description: The time that the trade happened in epoch seconds + timestampms: + type: TimestampType + $ref: '#/components/schemas/TimestampType' + description: The time that the trade happened in milliseconds + type: + type: string + enum: [Buy, Sell] + example: Buy + description: Will be either "Buy" or "Sell", indicating the side of the original order + aggressor: + type: boolean + description: If `true`, this order was the taker in the trade + fee_currency: + type: string + example: USD + description: Currency that the fee was paid in + fee_amount: + type: string + format: decimal + example: "1.23" + description: The amount charged + tid: + type: integer + example: 17379712930 + description: Unique identifier for the trade + order_id: + type: string + example: 123456789 + description: The order that this trade executed against + exchange: + type: string + example: gemini + description: Will always be "gemini" + break: + type: string + description: "Will only be present if the trade is broken. See `Break Types` below for more information." + description: "Contains an array of JSON objects with trade details." + + CancelAllResult: + type: object + properties: + result: + type: string + example: ok + details: + type: object + description: cancelledOrders/cancelRejects with IDs of both + properties: + cancelledOrders: + type: array + items: + type: integer + cancelRejects: + type: array + items: + type: integer + + MyTrade: + type: object + properties: + price: + type: string + example: 9100.00 + amount: + type: string + example: 1.5 + timestamp: + $ref: '#/components/schemas/TimestampType' + example: 1591084414 + timestampms: + $ref: '#/components/schemas/TimestampType' + example: 1591084414622 + type: + type: string + enum: [Buy, Sell] + example: Buy + aggressor: + type: boolean + example: true + fee_currency: + type: string + example: USD + fee_amount: + type: string + example: 13.65 + tid: + type: integer + format: int64 + example: 123456789 + order_id: + type: string + example: 123456789 + client_order_id: + type: string + exchange: + type: string + example: gemini + is_auction_fill: + type: boolean + example: false + break: + type: string + enum: ["", "trade correct"] + example: "" + + TradeVolume: + type: object + properties: + symbol: + type: string + example: btcusd + base_currency: + type: string + example: BTC + quote_currency: + type: string + example: USD + notional_currency: + type: string + example: USD + data_date: + type: string + example: 2020-06-02 + total_volume_base: + type: string + example: 10.5 + maker_buy_sell_ratio: + type: string + example: 1.2 + buy_maker_base: + type: string + example: 5.5 + buy_maker_notional: + type: string + example: 50050.00 + buy_maker_count: + type: integer + example: 10 + sell_maker_base: + type: string + example: 5.0 + sell_maker_notional: + type: string + example: 45500.00 + sell_maker_count: + type: integer + example: 8 + buy_taker_base: + type: string + example: 8.5 + buy_taker_notional: + type: string + example: 77350.00 + buy_taker_count: + type: integer + example: 15 + sell_taker_base: + type: string + example: 7.5 + sell_taker_notional: + type: string + example: 68250.00 + sell_taker_count: + type: integer + example: 12 + + Balance: + type: object + properties: + type: + type: string + enum: [exchange] + example: exchange + currency: + type: string + example: BTC + description: The currency symbol + amount: + type: number + example: 10.5 + description: | + The confirmed balance for the currency (also referred to as `confirmedBalance`). For crypto withdrawals, this value is **not** reduced until the withdrawal has been confirmed on the blockchain. This delay protects against blockchain reorganizations. Use the `available` field instead if you need balances that immediately reflect holds. + available: + type: number + example: 9.0 + description: | + The amount available for trading. This value is reduced **immediately** when an order hold or withdrawal hold is placed, making it the recommended field for tracking real-time spendable balances. + availableForWithdrawal: + type: number + example: 9.0 + description: The amount available for withdrawal + pendingWithdrawal: + type: number + example: 1.0 + description: The amount pending withdrawal + pendingDeposit: + type: number + example: 0.5 + description: The amount pending deposit + _timestamp: + type: string + format: date-time + example: "2024-03-16T00:00:00.000000Z" + description: Server-side monotonically increasing clock value as an ISO 8601 timestamp. Clients can use this value to detect and filter out stale responses that may occur due to load balancing or potential stale servers. + + NotionalVolume: + type: object + properties: + date: + type: string + format: date + example: '2020-06-02' + last_updated_ms: + type: integer + example: 1591084414622 + web_maker_fee_bps: + type: integer + example: 25 + web_taker_fee_bps: + type: integer + example: 35 + web_auction_fee_bps: + type: integer + example: 25 + api_maker_fee_bps: + type: integer + example: 10 + api_taker_fee_bps: + type: integer + example: 35 + api_auction_fee_bps: + type: integer + example: 20 + fix_maker_fee_bps: + type: integer + example: 10 + fix_taker_fee_bps: + type: integer + example: 35 + fix_auction_fee_bps: + type: integer + example: 20 + notional_30d_volume: + type: string + example: 1000000.00 + notional_1d_volume: + type: array + items: + type: object + properties: + date: + type: string + description: UTC date in `yyyy-MM-dd` format + notional_volume: + type: string + format: decimal + description: Notional volume value in USD for this single day + api_notional_30d_volume: + type: string + example: 750000.00 + fee_tier: + type: object + properties: + tier: + type: string + example: '0bps' + api_maker_fee_bps: + type: integer + example: 0 + api_taker_fee_bps: + type: integer + example: 10 + + NotionalBalance: + type: object + properties: + currency: + type: string + description: Currency code, see symbols and minimums + amount: + type: string + description: The current balance + amountNotional: + type: string + description: Amount, in notional + available: + type: string + description: The amount that is available to trade + availableNotional: + type: string + description: Available, in notional + availableForWithdrawal: + type: string + description: The amount that is available to withdraw + availableForWithdrawalNotional: + type: string + description: AvailableForWithdrawal, in notional + + Address: + type: object + properties: + address: + type: string + description: String representation of the cryptocurrency address + timestamp: + $ref: '#/components/schemas/TimestampType' + description: Creation date of the address + label: + type: string + description: If you provided a label when creating the address, it will be echoed back here + memo: + type: string + description: It would be present if applicable, it will be present for cosmos address + network: + type: string + description: The blockchain network for the address + + Transfer: + type: object + properties: + type: + type: string + enum: [Deposit, Withdrawal] + status: + type: string + enum: [Complete, Pending] + timestampms: + $ref: '#/components/schemas/TimestampType' + description: The timestamp in milliseconds + eid: + type: integer + format: int64 + description: The transfer ID + currency: + type: string + description: The currency transferred + amount: + type: string + description: The amount transferred + txHash: + type: string + description: The transaction hash if applicable + + V2Transfer: + type: object + properties: + type: + type: string + enum: [Deposit, Withdrawal, Reward, AdminDebit, AdminCredit] + description: The type of the transfer + status: + type: string + enum: [Complete, Pending, Advanced] + description: The status of the transfer + timestampms: + $ref: '#/components/schemas/TimestampType' + description: The timestamp in milliseconds + eid: + type: integer + format: int64 + description: The transfer event ID + currency: + type: string + description: The currency transferred + amount: + type: string + description: The amount transferred + network: + type: string + description: The blockchain network the transfer was executed on (e.g., `ethereum`, `solana`, `arbitrum`, `optimism`, `base`, `avalanche`). Not present for fiat or administrative transfers. + feeAmount: + type: string + description: The fee charged for the transfer + feeCurrency: + type: string + description: The currency in which the fee was charged + txHash: + type: string + description: The on-chain transaction hash, if applicable + method: + type: string + description: The transfer method (e.g., `ACH`, `CreditCard`) + destination: + type: string + description: The destination address for withdrawals + withdrawalId: + type: string + description: The unique withdrawal identifier + outputIdx: + type: integer + description: The output index for withdrawals + purpose: + type: string + description: The purpose or reason for administrative transfers + + WithdrawCryptoFundsResponse: + type: object + description: Response returned after submitting a v2 cryptocurrency withdrawal. + properties: + withdrawalId: + type: string + description: A unique ID for the withdrawal + address: + type: string + description: Standard string format of the withdrawal destination address + amount: + type: string + description: The withdrawal amount + currency: + type: string + description: The currency code of the withdrawn asset + fee: + type: string + description: The fee charged for the withdrawal + + InstantQuote: + type: object + properties: + quoteId: + type: integer + description: Unique ID for the quote. This is used in the execution of the order + maxAgeMs: + type: integer + description: Number of milliseconds until this quote price expires. Once expired, you will need to request a new quote + pair: + type: string + description: The symbol passed in the quote request + price: + type: string + description: The quoted price of the asset. This will not change when attempting execution + priceCurrency: + type: string + description: The currency in which the order is priced. Matches `CCY2` in the symbol + side: + type: string + enum: [buy, sell] + description: Either "buy" or "sell" + quantity: + type: string + description: The quantity of the asset to be bought or sold + quantityCurrency: + type: string + description: The currency label for the `quantity` field. Matches `CCY1` in the symbol + fee: + type: string + description: The fee quantity to be taken for the order upon execution + feeCurrency: + type: string + description: The currency label for the order + depositFee: + type: string + description: The deposit fee quantity. Will be applied if a debit card is used for the order. Will return 0 if there is no `depositFee` + depositFeeCurrency: + type: string + description: Currency in which `depositFee` is taken + totalSpend: + type: string + description: Total quantity to spend for the order. Will be the sum inclusive of all fees and amount to be traded. + totalSpendCurrency: + type: string + description: Currency of the `totalSpend` to be spent on the order + + ClearingOrder: + type: object + properties: + clearing_id: + type: string + description: The clearing ID + symbol: + type: string + description: The trading pair + price: + type: string + description: The order price + amount: + type: string + description: The order amount + side: + type: string + enum: [buy, sell] + status: + type: string + description: The order status + timestamp: + $ref: '#/components/schemas/TimestampType' + description: The timestamp + timestampms: + type: integer + description: The timestamp in milliseconds + is_confirmed: + type: boolean + description: Whether the order is confirmed + + Account: + type: object + properties: + name: + type: string + description: The account name + account_id: + type: string + description: The account ID + is_default: + type: boolean + description: Whether the account is the default account + created: + type: string + description: The creation date + + Transaction: + oneOf: + - type: object + description: Trade Reponse + title: Trade Reponse + properties: + account: + type: string + description: The account. + amount: + type: string + description: The quantity that was executed. + clientOrderId: + type: string + description: The client order ID, if defined. Otherwise an empty string. + price: + type: string + description: The price that the execution happened at. + timestampms: + $ref: '#/components/schemas/TimestampType' + description: The time that the trade happened in milliseconds. + side: + type: string + description: Indicating the side of the original order. + isAggressor: + type: boolean + description: If true, this order was the taker in the trade. + feeAssetCode: + type: string + description: The symbol that the trade was for + feeAmount: + type: string + description: The fee amount charged + orderId: + type: integer + format: int64 + description: The order that this trade executed against. + exchange: + type: string + description: Will always be "gemini". + isAuctionFill: + type: boolean + description: True if the trade was a auction trade and not an on-exchange trade. + isClearingFill: + type: boolean + description: True if the trade was a clearing trade and not an on-exchange trade. + tid: + type: integer + format: int64 + description: The trade ID. + symbol: + type: string + description: The symbol that the trade was for. + - type: object + description: Transfer Reponse + title: Transfer Reponse + properties: + timestampms: + $ref: '#/components/schemas/TimestampType' + description: The time that the trade happened in milliseconds. + source: + type: string + description: The account you are transferring from. + destination: + type: string + description: The account you are transferring to. + operationReason: + type: string + description: The operation reason. + status: + type: string + description: The status of the transfer. + eid: + type: integer + format: int64 + description: Transfer event id. + currency: + type: string + description: Currency code, see symbols + amount: + type: string + description: The quantity that was transferred. + method: + type: string + description: Type of transfer method. + correlationId: + type: integer + format: int64 + description: Correlation ID. + transferType: + type: string + description: Transfer type. + bankId: + type: string + description: Bank ID. + purpose: + type: string + description: Purpose. + transactionHash: + type: string + description: Supplies the transaction hash when available. + transferId: + type: string + description: Transfer ID. + withdrawalId: + type: string + description: Withdrawal ID. + clientTransferId: + type: string + description: Client Transfer ID. Client transfer ID is an optional client-supplied unique identifier for each withdrawal or internal transfer. + advanceEid: + type: integer + format: int64 + description: Deposit advance event ID. + pendingEid: + type: integer + format: int64 + description: Pending event ID. + withdrawalEid: + type: integer + format: int64 + description: Withdrawal event ID. + feeId: + type: string + description: Fee ID. + + + RevokeOauthTokenResponse: + type: object + properties: + message: + type: string + description: A message that indicates the token has been revoked for the account + + NetworkToken: + type: object + properties: + token: + type: string + description: The requested token identifier. + network: + type: array + items: + type: string + description: | + Array of supported blockchain networks for the token. Many tokens (especially stablecoins like USDC, USDT) are available on multiple networks. + + Supported networks include: `bitcoin`, `ethereum`, `solana`, `optimism`, `arbitrum`, `base`, `monad`, `avalanche`, `litecoin`, `bitcoincash`, `dogecoin`, `zcash`, `filecoin`, `tezos`, `polkadot`, `cosmos`, `xrpl`, `linea`, and more. + example: ["optimism", "solana", "base", "arbitrum", "monad", "avalanche", "ethereum"] + + NetworkAssets: + type: object + properties: + network: + type: string + description: The blockchain network identifier. + example: "ethereum" + assets: + type: array + items: + type: string + description: | + Alphabetically sorted array of enabled asset/token codes available on this network. Assets include both exchange-tradable and custody-supported tokens. + example: ["AAVE", "BAT", "DAI", "ETH", "LINK", "MATIC", "UNI", "USDC", "USDT", "WBTC"] + + FeePromos: + type: object + properties: + symbols: + type: array + items: + type: string + description: Symbols that currently have fee promos + + PriceFeedResponse: + type: array + items: + type: object + properties: + pair: + type: string + description: Trading pair symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + price: + type: string + description: Current price of the pair on the Gemini order book + percentChange24h: + type: string + description: 24 hour change in price of the pair on the Gemini order book + + ApprovedAddress: + type: object + properties: + network: + type: string + description: The network of the approved address. Network can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + scope: + type: string + description: Will return the scope of the address as either "account" or "group" + label: + type: string + description: The label assigned to the address + status: + type: string + description: The status of the address that will return as "active", "pending-time" or "pending-mua". The remaining time is exactly 7 days after the initial request. "pending-mua" is for multi-user accounts and will require another administator or fund manager on the account to approve the address. + createdAt: + type: string + description: UTC timestamp in millisecond of when the address was created. + address: + type: string + description: The address on the approved address list. + + ApprovedAddressesResponse: + type: object + description: Response envelope containing the approved withdrawal addresses. + properties: + approvedAddresses: + type: array + description: Array of approved addresses on both the account and group level. + items: + $ref: '#/components/schemas/ApprovedAddress' + + ApprovedAddressMessage: + type: object + properties: + message: + type: string + description: Status or confirmation message for the approved address request or removal. + result: + type: string + description: Result status (e.g. ok). + + CustodyFeeTransfer: + type: object + properties: + txTime: + type: integer + description: Time of Custody fee record in milliseconds + feeAmount: + type: string + description: The fee amount charged + feeCurrency: + type: string + description: Currency that the fee was paid in + eid: + type: integer + description: Custody fee event id + eventType: + type: string + description: Custody fee event type + + PaymentMethodsResponse: + type: object + properties: + balances: + type: array + description: Array of JSON objects with available fiat currencies and their balances. + items: + $ref: '#/components/schemas/PaymentMethodBalance' + banks: + type: array + description: Array of JSON objects with banking information + items: + $ref: '#/components/schemas/PaymentMethodBank' + + PaymentMethodBalance: + type: object + properties: + type: + type: string + description: Account type. Will always be `exchange` + currency: + type: string + description: Symbol for fiat balance. + amount: + type: string + description: Total account balance for currency. + available: + type: string + description: Total amount available for trading + availableForWithdrawal: + type: string + description: Total amount available for withdrawal + + PaymentMethodBank: + type: object + properties: + bank: + type: string + description: Name of bank account + bankId: + type: string + description: Unique identifier for bank account + + AddBankResponse: + type: object + properties: + referenceId: + type: string + description: Reference ID for the new bank addition request. Once received, send in a wire from the requested bank account to verify it and enable withdrawals to that account. + result: + type: string + description: Status result (e.g. ok). + + OpenPosition: + type: object + properties: + symbol: + type: string + description: The [symbol](/market-data/symbols-and-minimums) of the order. + instrument_type: + type: string + description: The type of instrument. Either "spot" or "perp". + quantity: + type: string + format: decimal + description: The position size. Value will be negative for shorts. + notional_value: + type: string + format: decimal + description: The value of position; calculated as (`quantity` * `mark_price`). Value will be negative for shorts. + realised_pnl: + type: string + format: decimal + description: The current P&L that has been realised from the position. + unrealised_pnl: + type: string + format: decimal + description: Current Mark to Market value of the positions. + average_cost: + type: string + format: decimal + description: The average price of the current position. + mark_price: + type: string + format: decimal + description: The current Mark Price for the Asset or the position. + + FundingAmountResponse: + type: object + properties: + symbol: + type: string + description: The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + fundingDateTime: + type: string + description: UTC date time in format `yyyy-MM-ddThh:mm:ss.SSSZ` format + fundingTimestampMilliSecs: + type: number + format: long + description: Current funding amount Epoc time. + nextFundingTimestamp: + type: number + format: long + description: Next funding amount Epoc time. + amount: + type: number + format: decimal + description: The dollar amount for a Long 1 position held in the symbol for funding period (1 hour) + estimatedFundingAmount: + type: number + format: decimal + description: The estimated dollar amount for a Long 1 position held in the symbol for next funding period (1 hour) + + StakingBalance: + type: object + properties: + type: + type: string + description: Will always be "Staking" + example: "Staking" + currency: + type: string + description: Currency code, see symbols and minimums + example: "MATIC" + balance: + type: number + format: decimal + description: The current Staking balance + example: 10 + available: + type: number + format: decimal + description: The amount that is available to trade + example: 0 + availableForWithdrawal: + type: number + format: decimal + description: The Staking amount that is available to redeem to exchange account + example: 10 + balanceByProvider: + type: object + additionalProperties: + type: object + properties: + balance: + type: number + format: decimal + description: The current Staking balance per providerId + example: 10 + + StakingDeposit: + type: object + properties: + transactionId: + type: string + description: A unique identifier for the staking transaction + example: "65QN4XM5" + providerId: + type: string + description: Provider Id, in uuid4 format + example: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: + type: string + description: Currency code, see [symbols](/market-data/symbols-and-minimums) + example: "MATIC" + amount: + type: number + format: decimal + description: The amount deposited + example: 30 + accrualTotal: + type: number + format: decimal + description: The total accrual + rates: + type: object + description: A JSON object including one or many rates. If more than one rate it would be an array of rates. + properties: + rate: + type: integer + description: Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + example: 540 + + StakingTransaction: + type: object + properties: + transactionId: + type: string + description: A unique identifier for the staking transaction + example: "MPZ7LDD8" + transactionType: + type: string + description: Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment + enum: [Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment] + example: "Redeem" + amountCurrency: + type: string + description: Currency code + example: "MATIC" + amount: + type: number + format: decimal + description: The amount that is defined by the transactionType above + example: 20 + priceCurrency: + type: string + description: A supported three-letter fiat currency code, e.g. usd + example: "USD" + priceAmount: + type: number + format: decimal + description: Current market price of the underlying token at the time of the reward + example: 0.1 + dateTime: + $ref: '#/components/schemas/TimestampType' + description: The time of the transaction in milliseconds + example: 1667418560153 + + StakingHistory: + type: object + properties: + providerId: + type: string + description: Provider Id, in uuid4 format + example: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + transactions: + type: array + items: + $ref: '#/components/schemas/StakingTransaction' + + StakingRate: + type: object + properties: + providerId: + type: string + description: Provider Id, in uuid4 format + example: "62bb4d27-a9c8-4493-a737-d4fa33994f1f" + rate: + type: number + format: decimal + description: Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + example: 429.386 + apyPct: + type: number + format: decimal + description: Staking interest APY (Expressed as a percentage derived from the rate and rounded to 1/10th of a percent.) + example: 4.39 + ratePct: + type: number + format: decimal + description: "`rate` expressed as a percentage" + example: 4.29386 + depositUsdLimit: + type: integer + description: Maximum new amount in USD notional of this crypto that can participate in Gemini Staking per account per month + example: 500000 + + StakingRateProvider: + type: object + description: Currency Symbol Keys + properties: + currency_symbol: + $ref: '#/components/schemas/StakingRate' + + StakingRateResponse: + type: object + description: Provider UUID Keys + properties: + provider_uuid: + $ref: '#/components/schemas/StakingRateProvider' + + StakingRewardPeriod: + type: object + properties: + providerId: + type: string + description: Provider Id, in uuid4 format + example: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: + type: string + description: Currency code, see [symbols](/market-data/symbols-and-minimums) + example: "MATIC" + apyPct: + type: number + format: decimal + description: Staking reward rate expressed as an APY at time of accrual. Interest on Staking balances compounds daily based on the simple rate which is available from `/v1/staking/rates/` + example: 5.75 + ratePct: + type: number + format: decimal + description: Rate expressed as a percentage + example: 5.592369 + numberOfAccruals: + type: integer + description: Number of accruals in the specific aggregate, typically one per day. If the rate is adjusted, new accruals are added. + example: 1 + accrualTotal: + type: number + format: decimal + description: The total accrual + example: 0.0065678 + firstAccrualAt: + type: string + description: Time of first accrual. In iso datetime with timezone format + example: "2022-08-23T20:00:00.000Z" + lastAccrualAt: + type: string + description: Time of last accrual. In iso datetime with timezone format + example: "2022-08-23T20:00:00.000Z" + + StakingRewards: + type: object + properties: + providerId: + type: string + description: Provider Id, in uuid4 format + example: "62b21e17-2534-4b9f-afcf-b7edb609dd8d" + currency: + type: string + description: Currency code, see [symbols](/market-data/symbols-and-minimums) + example: "MATIC" + accrualTotal: + type: number + format: decimal + description: The total accrual + example: 0.103994 + ratePeriods: + type: array + description: Array of JSON objects with period accrual information + items: + $ref: '#/components/schemas/StakingRewardPeriod' + + StakingRewardsProvider: + type: object + description: Currency Symbol Keys + properties: + currency_symbol: + $ref: '#/components/schemas/StakingRewards' + + + StakingRewardsResponse: + type: object + description: Provider UUID Keys + properties: + provider_uuid: + $ref: '#/components/schemas/StakingRewardsProvider' + + StakingWithdrawal: + type: object + properties: + transactionId: + type: string + description: A unique identifier for the staking transaction + example: "MPZ7LDD8" + amount: + type: number + format: decimal + description: The amount deposited + example: 20 + amountPaidSoFar: + type: number + format: decimal + description: The amount redeemed successfully + example: 20 + amountRemaining: + type: number + format: decimal + description: The amount pending to be redeemed + example: 0 + currency: + type: string + description: Currency code + example: "MATIC" + requestInitiated: + type: string + description: In ISO datetime with timezone format + example: "2022-11-02T19:49:20.153Z" + + FeeEstimateRequest: + type: object + required: + - request + - nonce + - address + - amount + - account + properties: + request: + type: string + description: The string `/v1/withdraw/{currencyCodeLowerCase}/feeEstimate` where `:currencyCodeLowerCase` is replaced with the currency code of a supported crypto-currency, e.g. `eth`, `aave`, etc. See [Symbols and minimums](/market-data/symbols-and-minimums) + example: /v1/withdraw/eth/feeEstimate + nonce: + $ref: '#/components/schemas/Nonce' + address: + type: string + description: Standard string format of cryptocurrency address + example: "0x31c2105b8dea834167f32f7ea7d877812e059230" + amount: + type: string + description: Quoted decimal amount to withdraw + example: '0.01' + account: + type: string + description: The name of the account within the subaccount group. + example: primary + + FeeEstimateResponse: + type: object + properties: + currency: + type: string + description: Currency code, see [symbols](/market-data/symbols-and-minimums). + example: ETH + fee: + type: string + description: The estimated gas fee + example: "{currency: 'ETH', value: '0'}" + isOverride: + type: boolean + description: Value that shows if an override on the customer's account for free withdrawals exists + example: false + monthlyLimit: + type: integer + description: Total nunber of allowable fee-free withdrawals + example: 1 + monthlyRemaining: + type: integer + description: Total number of allowable fee-free withdrawals left to use + example: 1 + + FeeEstimateV2Request: + type: object + required: + - request + - nonce + - address + - amount + properties: + request: + type: string + description: The string `/v2/withdraw/{network}/{ticker}/feeEstimate` where `{network}` is the blockchain network (e.g. `ethereum`, `bitcoin`, `solana`) and `{ticker}` is the currency code (e.g. `eth`, `btc`, `sol`). See [Symbols and minimums](/market-data/symbols-and-minimums) + example: /v2/withdraw/ethereum/eth/feeEstimate + nonce: + $ref: '#/components/schemas/Nonce' + address: + type: string + description: Standard string format of the destination cryptocurrency address + example: "0x31c2105b8dea834167f32f7ea7d877812e059230" + amount: + type: string + description: Quoted decimal amount to withdraw + example: '0.01' + account: + type: string + description: Required for Master API keys. The name of the account within the subaccount group. + example: primary + memo: + type: string + description: It would be present if applicable, it will be present for cosmos address. + + FeeEstimateV2Response: + type: object + properties: + currency: + type: string + description: Currency code, see [symbols](/market-data/symbols-and-minimums). + example: ETH + fee: + type: number + format: decimal + description: The estimated withdrawal fee as a decimal amount + example: 0.001 + isOverride: + type: boolean + description: Whether an override on the customer's account for free withdrawals exists + example: false + monthlyLimit: + type: integer + description: Total number of allowable fee-free withdrawals + example: 1 + monthlyRemaining: + type: integer + description: Total number of allowable fee-free withdrawals remaining + example: 1 + + RoleResponse: + type: object + required: + - isAuditor + - isFundManager + - isTrader + properties: + isAuditor: + type: boolean + description: "`True` if the Auditor role is assigned to the API keys. `False` otherwise." + isFundManager: + type: boolean + description: "`True` if the Fund Manager role is assigned to the API keys. `False` otherwise." + isTrader: + type: boolean + description: "`True` if the Trader role is assigned to the API keys. `False` otherwise." + counterparty_id: + type: string + description: _Only returned for master-level API keys_. The Gemini clearing counterparty ID associated with the API key making the request. + isAccountAdmin: + type: boolean + description: _Only returned for master-level API keys_.`True` if the Administrator role is assigned to the API keys. `False` otherwise. + + MarginResponse: + type: object + properties: + margin_assets_value: + type: string + format: decimal + description: The $ equivalent value of all the assets available in the current trading account that can contribute to funding a derivatives position. + initial_margin: + type: string + format: decimal + description: The $ amount that is being required by the accounts current positions and open orders. + available_margin: + type: string + format: decimal + description: The difference between the `margin_assets_value` and `initial_margin`. + margin_maintenance_limit: + type: string + format: decimal + description: The minimum amount of `margin_assets_value` required before the account is moved to liquidation status. + leverage: + type: string + format: decimal + description: The ratio of Notional Value to Margin Assets Value. + notional_value: + type: string + format: decimal + description: The $ value of the current position. + estimated_liquidation_price: + type: string + format: decimal + description: The estimated price for the asset at which liquidation would occur. + initial_margin_positions: + type: string + format: decimal + description: The contribution to `initial_margin` from open positions. + reserved_margin: + type: string + format: decimal + description: The contribution to `initial_margin` from open orders. + reserved_margin_buys: + type: string + format: decimal + description: The contribution to `initial_margin` from open BUY orders. + reserved_margin_sells: + type: string + format: decimal + description: The contribution to `initial_margin` from open SELL orders. + buying_power: + type: string + format: decimal + description: The amount of that product the account could purchase based on current `initial_margin` and `margin_assets_value`. + selling_power: + type: string + format: decimal + description: The amount of that product the account could sell based on current `initial_margin` and `margin_assets_value`. + + MoneyAmount: + type: object + properties: + currency: + type: string + description: The currency code (e.g., "USD", "BTC", "ETH") + example: "USD" + value: + type: string + format: decimal + description: The amount in the specified currency + example: "10000.00" + required: + - currency + - value + + LiquidationRisk: + type: object + properties: + lossPercentage: + type: string + format: decimal + description: The percentage loss from current value that would trigger liquidation, formatted as decimal (e.g., "0.1550" = 15.50%) + example: "0.1550" + liquidationPrice: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The estimated price at which liquidation would occur (optional, may not be present for all positions) + required: + - lossPercentage + + InterestRateInfo: + type: object + properties: + rate: + type: string + format: decimal + description: The interest rate as a decimal string + example: "0.00001141552511" + interval: + type: string + enum: [hour] + description: The time interval for the rate (currently only "hour" is supported) + example: "hour" + required: + - rate + - interval + + MarginAccountSummary: + type: object + properties: + marginAssetValue: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The total value of all assets available in the margin account that can contribute to funding positions + availableCollateral: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The amount of collateral available for new positions or withdrawals + notionalValue: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The total value of all open positions + totalBorrowed: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The total amount currently borrowed across all currencies + leverage: + type: string + format: decimal + description: The current leverage ratio (notionalValue / marginAssetValue) + example: "1.5" + buyingPower: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The maximum value that can be purchased with available collateral + sellingPower: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The maximum value that can be sold with available collateral + liquidationRisk: + allOf: + - $ref: '#/components/schemas/LiquidationRisk' + description: Liquidation risk information (only present if positions exist) + interestRate: + allOf: + - $ref: '#/components/schemas/InterestRateInfo' + description: Current interest rate on borrowed amounts (only present if borrows exist) + reservedBuyOrders: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: Collateral reserved for open buy orders + reservedSellOrders: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: Collateral reserved for open sell orders + required: + - marginAssetValue + - availableCollateral + - notionalValue + - totalBorrowed + - leverage + - buyingPower + - sellingPower + - reservedBuyOrders + - reservedSellOrders + + MarginInterestRate: + type: object + properties: + currency: + type: string + description: The currency code (e.g., "BTC", "ETH", "USD") + example: "BTC" + borrowRate: + type: string + format: decimal + description: The hourly borrow rate as a decimal + example: "0.00001141552511" + borrowRateDaily: + type: string + format: decimal + description: The daily borrow rate (hourly rate × 24) + example: "0.00027397260264" + borrowRateAnnual: + type: string + format: decimal + description: The annualized borrow rate (daily rate × 365) + example: "0.1" + lastUpdated: + type: integer + format: int64 + description: Unix timestamp in milliseconds when the rate was last updated + example: 1700000000000 + required: + - currency + - borrowRate + - borrowRateDaily + - borrowRateAnnual + - lastUpdated + + MarginRatesResponse: + type: object + properties: + rates: + type: array + items: + $ref: '#/components/schemas/MarginInterestRate' + description: Array of interest rates for all borrowable currencies + required: + - rates + + MarginRiskStats: + type: object + properties: + marginAssetValue: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The total value of all assets available in the margin account + availableCollateral: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The amount of collateral available for new positions + notionalValue: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The total value of all open positions + totalBorrowed: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The total amount currently borrowed + leverage: + type: string + format: decimal + description: The leverage ratio + example: "1.5" + reservedBuyOrders: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: Collateral reserved for open buy orders + reservedSellOrders: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: Collateral reserved for open sell orders + buyingPower: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The maximum value that can be purchased + sellingPower: + allOf: + - $ref: '#/components/schemas/MoneyAmount' + description: The maximum value that can be sold + liquidationRisk: + allOf: + - $ref: '#/components/schemas/LiquidationRisk' + description: Liquidation risk information (only present if applicable) + required: + - marginAssetValue + - availableCollateral + - notionalValue + - totalBorrowed + - leverage + - reservedBuyOrders + - reservedSellOrders + - buyingPower + - sellingPower + + MarginOrderPreview: + type: object + properties: + preorder: + allOf: + - $ref: '#/components/schemas/MarginRiskStats' + description: Margin risk statistics before the order would be executed + postorder: + allOf: + - $ref: '#/components/schemas/MarginRiskStats' + description: Margin risk statistics after the order would be executed + required: + - preorder + - postorder + + Quantity: + type: object + properties: + currency: + type: string + description: The currency code of the quantity. + value: + type: string + format: decimal + description: The value of the quantity. + required: + - currency + - value + + FundingTransfer: + type: object + properties: + eventType: + type: string + description: Event type + timestamp: + allOf: + - $ref: '#/components/schemas/TimestampType' + description: Time of the funding payment + assetCode: + type: string + description: Asset symbol + action: + type: string + enum: [Credit, Debit] + description: Credit or Debit + quantity: + allOf: + - $ref: '#/components/schemas/Quantity' + description: A nested JSON object describing the transaction amount + instrumentSymbol: + type: string + description: Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + required: + - eventType + - timestamp + - assetCode + - action + - quantity + + FundingPayment: + type: object + required: + - eventType + - hourlyFundingTransfer + properties: + eventType: + type: string + enum: [Hourly Funding Transfer] + description: Event type + hourlyFundingTransfer: + $ref: '#/components/schemas/FundingTransfer' + + FundingPaymentReportItem: + type: object + required: + - eventType + - timestamp + - assetCode + - action + - quantity + properties: + eventType: + type: string + enum: [Hourly Funding Transfer] + description: Event type + timestamp: + allOf: + - $ref: '#/components/schemas/TimestampType' + description: Time of the funding payment + assetCode: + type: string + description: Asset symbol + action: + type: string + enum: [Credit, Debit] + description: Credit or Debit + quantity: + allOf: + - $ref: '#/components/schemas/Quantity' + description: A nested JSON object describing the transaction amount + instrumentSymbol: + type: string + description: Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + + RiskStatsResponse: + type: object + properties: + product_type: + type: string + enum: [PerpetualSwapContract] + description: Contract type for which the symbol data is fetched + mark_price: + type: string + format: decimal + description: Current mark price at the time of request + index_price: + type: string + format: decimal + description: Current index price at the time of request + open_interest: + type: string + format: decimal + description: string representation of decimal value of open interest + open_interest_notional: + type: string + format: decimal + description: string representation of decimal value of open interest notional + + FxRate: + type: object + properties: + fxPair: + type: string + description: The requested currency pair + example: AUDUSD + rate: + type: number + format: double + description: The exchange rate + example: 0.69 + asOf: + $ref: '#/components/schemas/TimestampType' + description: The timestamp (in Epoch time format) that the requested fxrate has been retrieved for + example: 1594651859000 + provider: + type: string + description: The market data provider + example: bcb + benchmark: + type: string + description: The market for which the retrieved price applies to + example: Spot + + Candle: + type: array + items: + type: number + format: double + minItems: 6 + maxItems: 6 + description: Array of [timestamp (ms), open, high, low, close, volume] + example: + - [1559755800000, 7781.6, 7820.23, 7776.56, 7819.39, 34.7624802159] + - [1559755800000, 7781.6, 7829.46, 7776.56, 7817.28, 43.4228281059] + + CandleResponse: + type: array + items: + $ref: '#/components/schemas/Candle' + + TickerInfo: + type: object + properties: + symbol: + type: string + description: The trading pair symbol + example: BTCUSD + open: + type: string + format: decimal + description: Open price from 24 hours ago + example: "9121.76" + high: + type: string + format: decimal + description: High price from 24 hours ago + example: "9440.66" + low: + type: string + format: decimal + description: Low price from 24 hours ago + example: "9106.51" + close: + type: string + format: decimal + description: Close price (most recent trade) + example: "9347.66" + changes: + type: array + description: Hourly prices descending for past 24 hours + items: + type: string + format: decimal + example: ["9365.1", "9386.16", "9373.41", "9322.56", "9268.89", "9265.38"] + bid: + type: string + format: decimal + description: Current best bid + example: "9345.70" + ask: + type: string + format: decimal + description: Current best offer + example: "9347.67" + + parameters: + timestampParam: + name: timestamp + in: path + required: true + schema: + $ref: '#/components/schemas/TimestampType' + description: | + The timestamp to pull the FX rate for. + + Gemini strongly recommends using milliseconds instead of seconds for timestamps. + example: 1591084414622 + + symbolParam: + name: symbol + in: path + required: true + schema: + type: string + description: | + Trading pair symbol

+ + `BTCUSD`, etc. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols). + + currencyParam: + name: currency + in: path + required: true + schema: + type: string + description: Either a fiat currency, e.g. `usd` or `gbp`, or a supported crypto-currency, e.g. `gusd`, `btc`, `eth`, `aave`, etc. + + networkParam: + name: network + in: path + required: true + schema: + type: string + description: Can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + + apiKeyAuth: + name: X-GEMINI-APIKEY + in: header + required: true + description: Your API key + schema: + type: string + payloadAuth: + name: X-GEMINI-PAYLOAD + in: header + required: true + description: Base64-encoded JSON payload + schema: + type: string + signatureAuth: + name: X-GEMINI-SIGNATURE + in: header + required: true + description: HEX-encoded HMAC-SHA384 of payload signed with API secret + schema: + type: string + contentType: + name: Content-Type + in: header + required: false + schema: + type: string + default: "text/plain" + contentLength: + name: Content-Length + in: header + required: false + schema: + type: string + default: "0" + cacheControl: + name: Cache-Control + in: header + required: false + schema: + type: string + default: no-cache + + responses: + BadRequest: + description: Bad request - malformed request or invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + result: error + reason: InvalidSignature + message: Invalid signature for this request + Unauthorized: + description: Unauthorized - missing or invalid authentication + content: + application/json: + schema: + type: object + $ref: '#/components/schemas/ErrorResponse' + example: + result: error + reason: MissingApikeyHeader + message: Must provide 'X-GEMINI-APIKEY' header + ApiKeyIpFilteringFailure: + description: ApiKey fails IP Filtering Check + content: + application/json: + schema: + type: object + $ref: '#/components/schemas/ErrorResponse' + example: + result: error + reason: ApiKeyIpFilteringFailure + message: ApiKey fails IP Filtering Check for some accounts + NotFound: + description: Resource not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + result: error + reason: EndpointNotFound + message: API entry point not found + TooManyRequests: + description: Too many requests - you have exceeded the rate limit + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + result: error + reason: Too Many Requests + message: Too Many Requests + InternalError: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + result: error + reason: Internal Server Error + message: Unexpected server error occurred. diff --git a/specs/overlays/gemini-wire-exceptions.yaml b/specs/overlays/gemini-wire-exceptions.yaml new file mode 100644 index 00000000..18e82254 --- /dev/null +++ b/specs/overlays/gemini-wire-exceptions.yaml @@ -0,0 +1,37 @@ +version: 1 +exceptions: + - id: rest-nonce-json-type + summary: Signed REST payload nonce is an unquoted JSON number in TypeScript and a JSON string in Go. + typescript: src/transport/http.ts:1036 writes rawJSON(nonce) + go: auth/hmac.go:276-283 marshals the nonce string + tolerance: Conformance compares the nonce by decimal text, accepting a JSON number or a numeric JSON string. + cases: [http/hmac-requests/private-post-with-body, http/hmac-requests/private-post-empty-body] + - id: rest-payload-key-order + summary: Signed payload key order differs (TypeScript insertion order, Go lexicographic). + tolerance: Signature is verified against each SDK's own base64 payload, so key order is free on the wire. + cases: [http/hmac-requests/private-post-with-body] + - id: ws-subscription-id-scope + summary: Subscribe frame id is session-local in TypeScript and process-global in Go; neither exposes an injection seam. + tolerance: Conformance asserts method and params, and that id is a positive integer. + cases: [websocket/subscriptions/public-trades] + - id: ws-inbound-symbol-case + summary: Go uppercases the inbound top-level symbol; TypeScript delivers wire casing unchanged. + go: websocket/client_dispatch.go:113-158 + tolerance: Conformance compares symbol fields case-insensitively. + cases: [websocket/events/trade] + - id: int64-static-typing + summary: Static int64 typing differs — TypeScript keys off format int64 only; Go additionally widens the overlay's wide-integer names. + tolerance: Declared in specs/overlays/numeric-types.yaml as appliesTo [go]; runtime exactness is asserted instead. + cases: [json/wide-integer-unsafe] + - id: http-406-insufficient-funds + summary: TypeScript maps bare HTTP 406 to InsufficientFunds; Go has no 406 sentinel and needs the reason field. + tolerance: Fixtures always carry the InsufficientFunds reason, which both SDKs classify. + cases: [] + - id: rest-query-signing + summary: TypeScript can include the query string in the signed request path (signQuery); Go signs URL path only. + tolerance: Signing fixtures use query-free paths. + cases: [] + - id: candle-timeframe-spelling + summary: Spec enum is 1m/5m/15m/30m/1h/6h/1d while its prose mentions 1day; the Go service forwards the caller's string unchanged and its own test uses 1hr. + tolerance: Unresolved upstream; no conformance case asserts a timeframe spelling. + cases: [] diff --git a/specs/overlays/numeric-types.yaml b/specs/overlays/numeric-types.yaml new file mode 100644 index 00000000..9d9459cd --- /dev/null +++ b/specs/overlays/numeric-types.yaml @@ -0,0 +1,78 @@ +version: 1 + +# Raw-byte format aliases applied before the document is parsed. +formatAliases: + appliesTo: [go] + reason: >- + openapi-typescript maps the unaliased formats to `number`; widening the + published TypeScript types to bigint would break @gemini-markets/sdk + consumers. Go rewrites them so wire-wide integers never land on a + platform-sized int. + rules: + - from: long + to: int64 + - from: integer + to: int64 + +# `format: decimal` runtime representation per language. +decimalFormat: + appliesTo: [go, typescript] + format: decimal + go: + numberSchema: types.DecimalNumber + stringSchema: types.Decimal + importPath: github.com/gemini/developer-platform/packages/sdk-go/types + importAlias: types + typescript: + numberSchema: number + stringSchema: string + exactArithmetic: src/utils/decimal.ts + +# Identifier/timestamp fields whose wire values exceed a platform int. +# Matched against schema property names AND parameter names; schemas with +# allOf/anyOf/oneOf keep their declared unions. +wideIntegers: + appliesTo: [go] + reason: >- + TypeScript preserves exactness at parse time (parseLosslessJson promotes + unsafe integers to bigint), so it needs no name list; widening the generated + static types would break the published package. + matches: [schemaProperty, parameterName] + skipComposedSchemas: true + properties: + - cancelRejects + - cancelledOrders + - eid + - last_updated_ms + - order_id + - quoteId + - since_tid + - tid + - timestamp_nanos + - timestampms + - txTime + +# Unsigned 64-bit request fields, declared by the specification itself. +unsignedIntegers: + appliesTo: [go, typescript] + extension: x-unsigned-int64 + locations: + - schema: CancelOrderRequest + property: order_id + - schema: OrderStatusRequest + property: order_id + +# Overrides the published specification cannot express. +schemaOverrides: + appliesTo: [go] + reason: >- + Go needs an explicit exact-decimal or int64 type where the specification + declares a bare JSON number; TypeScript keeps the generated number/string. + decimalFields: + - schema: Balance + properties: [amount, available, availableForWithdrawal, pendingWithdrawal, pendingDeposit] + int64Fields: + - schema: NewOrderRequest + property: nonce + int64OneOfVariants: + - schema: Nonce diff --git a/specs/refresh.mjs b/specs/refresh.mjs new file mode 100644 index 00000000..b1d40c23 --- /dev/null +++ b/specs/refresh.mjs @@ -0,0 +1,26 @@ +import { createHash } from "node:crypto"; +import { mkdir, readFile, writeFile } from "node:fs/promises"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const specsDir = dirname(fileURLToPath(import.meta.url)); +const manifestPath = join(specsDir, "SOURCES.json"); +const manifest = JSON.parse(await readFile(manifestPath, "utf8")); + +for (const entry of manifest.specs) { + const response = await fetch(entry.url); + if (!response.ok) throw new Error(`failed to fetch ${entry.url}: HTTP ${response.status}`); + + const bytes = Buffer.from(await response.arrayBuffer()); + const sha256 = createHash("sha256").update(bytes).digest("hex"); + const unchanged = entry.sha256 === sha256; + const destination = join(specsDir, entry.path); + await mkdir(dirname(destination), { recursive: true }); + await writeFile(destination, bytes); + + entry.sha256 = sha256; + if (!unchanged) entry.fetchedAt = new Date().toISOString(); + console.log(`${unchanged ? "unchanged" : "updated"} ${entry.id} ${sha256}`); +} + +await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);