NAV
http python

CHANGE LOG

2026-10-06

2026-09-17

2026-09-16

2026-07-23

2026-07-17

2026-07-16

2026-07-15

2026-06-24

2026-02-20

Update Error codes and minor cleanups

2026-01-14

Update documentation. Minor cleanups.

2025-10-31

Support Ethereum Fusaka upgrade

2025-10-11

Updated contract address for mainnet and hoodi

2025-07-08

2025-06-26

2025-06-18

2025-05-14

2025-05-06

2025-04-16

2025-04-02

2025-03-28

2025-03-25

Updated Production Hoodi API and WS base url Updated testchain url for example usage Updated Validator API and User deposit collateral API

2025-03-15

2025-02-21

2025-01-12

2024-12-01

2024-10-01

INTRODUCTION

Welcome

ETHGas provides REST and WebSocket APIs for market data, orders, and account operations.

Code samples are HTTP and Python. Switch languages with the tabs at the upper right.

Support: info@ethgas.com or Telegram.

Environments

Environment Chain RPC URL Chain ID API base URL Websocket base URL Collateral Contract
Mainnet Ethereum Chain https://eth.llamarpc.com 1 https://prod-mainnet.ethgas.com wss://prod-mainnet.ethgas.com/ws 0x3314Fb492a5d205A601f2A0521fAFbD039502Fc3
Testnet Hoodi Chain https://ethereum-hoodi-rpc.publicnode.com 560048 https://hoodi.app.ethgas.com wss://hoodi.app.ethgas.com/ws 0x104Ef4192a97E0A93aBe8893c8A2d2484DFCBAF1

Connecting to ETHGas

Set ETHGAS_BASE_URL from the table above. This example reads ETHGAS_PRIVATE_KEY from the environment. Use a signing service in production, and keep keys and tokens out of logs.

import json
import os
import requests
from eth_account import Account, messages

base_url = os.environ["ETHGAS_BASE_URL"].rstrip("/")
signer = Account.from_key(os.environ["ETHGAS_PRIVATE_KEY"])
session = requests.Session()
session.headers["User-Agent"] = "ethgas-docs-example/1.0"

def data_or_error(response):
    response.raise_for_status()
    if "application/json" not in response.headers.get("Content-Type", "").lower():
        raise RuntimeError("Expected an application/json response")
    body = response.json()
    if not body.get("success"):
        raise RuntimeError(f"ETHGas error {body.get('errorCode')}: {body.get('errorMsgKey')}")
    return body["data"]

challenge = data_or_error(session.post(
    base_url + "/api/v1/user/login", data={"addr": signer.address}, timeout=30
))
typed_data = json.loads(challenge["eip712Message"])
signed = signer.sign_message(messages.encode_typed_data(full_message=typed_data))
login = data_or_error(session.post(
    base_url + "/api/v1/user/login/verify",
    data={"addr": signer.address, "nonceHash": challenge["nonceHash"],
          "signature": "0x" + bytes(signed.signature).hex()},
    timeout=30,
))
access_token = login["accessToken"]["token"]
# Session retains the x_auth_refresh_token cookie from verification.
accounts = data_or_error(session.get(
    base_url + "/api/v1/user/accounts",
    headers={"Authorization": "Bearer " + access_token}, timeout=30
))
print(accounts)

# Use the same session/client context; an access bearer is not required here.
refreshed = data_or_error(session.post(base_url + "/api/v1/user/login/refresh", timeout=30))
access_token = refreshed["accessToken"]["token"]
# To log out later, POST /api/v1/user/logout with this session and bearer token.

This example signs in and loads your accounts. It does not place an order. Sign the EIP-712 message returned by login.

  1. Request a challenge.
  2. Verify the signature. Send data.accessToken.token as Authorization: Bearer {{access_token}}.
  3. Keep the x_auth_refresh_token cookie and refresh before exp. exp is Unix time in seconds. Sign in again if refresh fails.

Market data under /api/v1/p/ is public. Login, verify, and refresh are public. Other /api/v1/ routes require a bearer token. A valid token still needs permission for the account you use.

For WebSocket, connect to the WebSocket base URL and send login with the access token. Units, pagination, and retries are in the Integration guide.

REST API

Response structure

A successful JSON response normally contains success: true and data. Application failures use success: false, errorCode and errorMsgKey. HTTP 200 alone does not mean the operation succeeded. Cancellation and withdrawal batches also require checking each item/result list.

Name Type Presence / description
success boolean Present in application JSON responses.
data object Operation-specific payload. May be empty; some typed error responses omit it.
errorCode integer Application error code on failure; usually omitted on success.
errorMsgKey string Stable message key on failure; usually omitted on success.

Optional fields are omitted when empty. Ignore response fields you do not use.

HTTP status

Status Meaning What to do
200 Success, or an application error in the JSON body Check success, then any per-item codes.
400 Invalid request Correct the request. Validation uses code 23. An unsupported method uses 24.
401 Not signed in. Code 1, with WWW-Authenticate: Bearer Refresh once, or sign in again.
403 Not permitted. Code 1 Use an account you are allowed to access.
415 Unsupported content type. Code 25 Use the content type shown for the endpoint.
429 Busy. Code 20 Wait for Retry-After, then retry a read.
500 Server error. Code 21 Look up the result before repeating a create, cancel, withdrawal, or bundle.
503 Unavailable. Code 20 or 26, with Retry-After Retry a read after the delay. Look up a request whose result you did not receive.

Check the HTTP status and Content-Type before parsing. A proxy or network error can return a non-JSON body.

Busy responses (429 and 503) include Retry-After and data.retryAfterSeconds, in seconds, plus X-Request-ID and data.requestId. An application error from an endpoint can omit those fields.

Example error. The HTTP status can be 200:

{"success":false,"errorCode":66,"errorMsgKey":"error.accountId.required","data":{}}

See Error Codes and the Integration guide.

Integration guide

Use this guide with the endpoint pages. It covers request format, units, pagination, and retries. Routes use the /api/v1 prefix. Read the changelog before upgrading a client.

Reference and examples

Follow the field names, units, and content type on each endpoint. The server can ignore a field it does not recognize, so check names against that page.

Accounts, markets, slots, and signatures in the examples are samples. Sign in, select your account and an open market, then check price and quantity against that market. Use Hoodi for testing. Submit your own signatures and signed transactions.

openapi-core.json covers authentication and order creation and cancellation. All other operations are described in this reference.

Request encoding

JSON operations require Content-Type: application/json and a JSON body. Query parameters do not replace that body.

Other POST operations accept URL-encoded form fields, as shown on the endpoint. Send tokens and signatures in the form body. Send GET parameters in the query string, and quote curl URLs that contain &.

Use JSON booleans true and false, and send amounts as decimal strings. Use the list format shown for that endpoint: a JSON array, or a comma-separated form or query value.

Types and units

Concept Format
Decimal amount or price Decimal string. Trailing zeros may be omitted. Use decimal arithmetic.
Order price ETH per gas, within the market minPrice, maxPrice, and priceStep.
Whole-block quantity 1.
Inclusion quantity Decimal gas quantity, within the market minimum, maximum, and step.
REST timestamps Epoch milliseconds, unless the field gives another format.
JWT iat and exp Epoch seconds.
Dashboard slotTime and paymentTime UTC ISO-8601 with milliseconds, such as 2026-10-01T00:00:00.000Z.
Slot Ethereum slot number.
Identifiers Integers. Some values exceed the range JavaScript stores exactly, so use an integer-safe parser.
Optional fields Omitted when empty. Send null only when the endpoint says to.
Hex values Use the prefix and length given for the field. Dashboard history may omit 0x.

Accounts

Omitting accountId on a private order or position list selects your preconf account. An account you name must be your own, or an account shared with you for reading. Orders and withdrawals use their own permissions.

On withdrawal history and status, a readable accountId limits the result to that account. Omitting it returns your own history. Deposit history is available to the wallet owner. Transaction lists may require accountId. Where a user setting uses the owner account, the endpoint says so.

Pagination and filters

Order lists page by order ID. The cursor is exclusive: ascending returns IDs above startId, and descending returns IDs below it. Keep the same filters and direction, and send the last returned ID as the next startId.

List Defaults
Private whole-block orders Ascending, no cursor, limit 10, maximum 1000.
Private inclusion orders Descending, no cursor, limit 10, maximum 1000.
Private all-orders, both markets Ascending, no cursor, limit 10, maximum 1000.
Public order lists Ascending, no cursor, limit 10, maximum 1000.
Private position lists Descending, enable=true, limit 10, maximum 1000. The cursor is a slot.
Operator block and payment history limit 100, maximum 200, offset 0. A non-positive limit uses 100. A negative offset uses 0.

Omit startId on the first page. Descending with startId=0 returns no orders.

For all-orders, hasNextPage is true when another matching order exists. nextCursor is the last order ID in that page. The last page has hasNextPage false and no nextCursor. Keep filters unchanged between pages, because the list can change.

done=true returns orders with status 10. It does not include every canceled or expired order. A request cannot ask for open orders and done orders together. The public whole-block parameter is onbook. Public inclusion lists and private order lists use onBook.

These order lists return HTTP 400 and error code 23 when limit is 0 or negative, and they cap a larger limit at 1000.

Block and payment history can change when a payment is updated. Keep the same filters, store each record once, and check totals again after you export.

Mutations, retries and idempotency

Outcome What to do
Read timeout, 429, or 503 Wait, then retry with backoff. Follow Retry-After when the response includes it.
400, 415, or a validation error Correct the request before trying again.
401 Refresh the session once. Sign in again if refresh fails.
HTTP 200 with success false Use errorCode. See Error Codes.
Failed cancellation item Read each data.orders[].code. The response can still have success true.
Order timeout Keep the same clientOrderId and look up the order before submitting again.
Withdrawal timeout or partial batch Read both result lists, then look up the request IDs already sent.
Bundle timeout or replacement Check the slot, account, and replacement UUID before submitting again.

clientOrderId is 1 to 32 letters or digits (^[a-zA-Z0-9]{1,32}$). A value already in use returns error code 58. Look up the existing order when you receive that code. Withdrawals have no equivalent client request ID.

Some operations treat a missing field as a choice:

When the service is busy

A busy service returns HTTP 429 with error code 20, or HTTP 503 with error code 20 or 26. The response includes Retry-After and data.retryAfterSeconds, in seconds. Wait at least that long before retrying a read. If you did not receive the result of a create, cancel, withdrawal, or bundle request, look it up before sending it again.

These responses include X-Request-ID and data.requestId.

Authentication

Login accepts query parameters or form fields. The examples use form fields. The full sign-in flow is in Connecting to ETHGas. Each challenge is single-use. Sign the message returned by that call.

POST /api/v1/user/login

Public endpoint. Obtain a challenge to prove control of the EOA address. The name parameter is not supported here; use the profile update endpoint for a display name.

curl --request POST "$ETHGAS_BASE_URL/api/v1/user/login" \
  --data-urlencode "addr=$ETHGAS_ADDRESS"

Request

Parameter Required Type Description
addr YES string EOA address, 20-byte hex.

Response Body

Name Type Description
status string verify when the challenge is ready.
eip712Message string JSON-encoded EIP-712 object. Parse this string once before signing the returned typed data unchanged.
nonceHash string Four-byte nonce hash in hex. Correlates this challenge with verification.

An invalid address returns application code 100011. Verification rejects a used nonce (100012) or unknown nonce (100013). A successful challenge response is not an authenticated session.

POST /api/v1/user/login/verify

Public endpoint. Submit the signature for the returned challenge. User-Agent is required. The server sets the x_auth_refresh_token refresh cookie; retain it. The refresh token is not a field in the JSON response.

curl --request POST "$ETHGAS_BASE_URL/api/v1/user/login/verify" \
  --header 'User-Agent: ethgas-docs-example/1.0' \
  --cookie-jar ethgas-cookies.txt \
  --data-urlencode "addr=$ETHGAS_ADDRESS" \
  --data-urlencode "nonceHash=$ETHGAS_NONCE_HASH" \
  --data-urlencode "signature=$ETHGAS_SIGNATURE"

Request

Parameter Required Type Description
addr YES string EOA address used for the challenge.
nonceHash YES string Value returned by login.
signature YES string Hex EIP-712 signature for that challenge.
User-Agent YES header string Preserve the same client context for refresh.

Response Body

Name Type Description
user object User details, including available accounts.
accessToken object Token object, not a bearer string.
accessToken.token string Value for the Authorization Bearer header.
accessToken.data object Decoded header and payload metadata.
accessToken.data.payload.iat integer JWT issue time, epoch seconds.
accessToken.data.payload.exp integer JWT expiry time, epoch seconds.

Incorrect addresses/signatures/nonces can return HTTP 400 with an application error. Do not log the response token or cookie jar; treat both as credentials.

POST /api/v1/user/login/refresh

No access token is required. Send the refresh cookie from login, or send refreshToken in the form body. If you send both, the cookie is used. Use the same User-Agent as login. A different client or country can make refresh fail. The response contains a new access token. It does not contain a new refresh token.

curl --request POST "$ETHGAS_BASE_URL/api/v1/user/login/refresh" \
  --header 'User-Agent: ethgas-docs-example/1.0' \
  --cookie ethgas-cookies.txt

Request

Parameter Required Type Description
x_auth_refresh_token ONE SOURCE cookie string Cookie retained from verification.
refreshToken ONE SOURCE form/query string Alternative when no refresh cookie is available. Prefer a form body.
User-Agent YES header string Required client context.

Response Body

Name Type Description
user object Current user details.
accessToken object Same token-object structure as verification; use accessToken.token.

A missing refresh token returns HTTP 400 and code 100016. An invalid token or a different client returns 100018. An unknown session returns 100019. Sign in again after refresh fails.

POST /api/v1/user/logout

Requires the current access bearer and a refresh credential from cookie or form/query parameter. If both refresh sources are present, they must be identical; conflicting values produce code 100017. The refresh credential must belong to the current user. Successful logout removes the associated login session and clears the refresh cookie.

curl --request POST "$ETHGAS_BASE_URL/api/v1/user/logout" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --cookie ethgas-cookies.txt \
  --cookie-jar ethgas-cookies.txt

Request

Parameter Required Type Description
x_auth_refresh_token ONE SOURCE cookie string Refresh credential.
refreshToken ONE SOURCE form/query string Alternative refresh credential; must match the cookie if both are sent.

Response Body

{"success":true,"data":{}}

A missing or invalid refresh token returns an application error. Check success as well as the HTTP status. Logout ends the refresh session. An access token that was already issued remains valid until exp.

User

POST /api/v1/user/update

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/update?displayName=NewDisplayName"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/update"

payload = {
    'displayName': 'NewDisplayName'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "user": {
            "userId": 73,
            "address": "0xcc8f16b4e20feb0e7eb5a4725451db6316afa8f",
            "status": 1,
            "userType": 1,
            "userClass": 1,
            "displayName": "XXXXX",
            "payoutAddress": "0xde88f16b4e20feb0525289041db6316afa8f",
            "locked": false,
            "collateralPerSlot": "0",
            "onchainPayout": true,
            "accounts": [
                {
                    "accountId": 2170,
                    "userId": 73,
                    "type": 1,
                    "name": "Current",
                    "status": 1,
                    "updateDate": 1751854737000
                },
                {
                    "accountId": 2171,
                    "userId": 73,
                    "type": 2,
                    "name": "InPreconf",
                    "status": 1,
                    "updateDate": 1751854737000
                }
            ]
        }
    }
}

Update user display name.

Fails with USER_LOCKED if the user has locked their account (POST /api/v1/user/lock).

Request

Parameter Required Type Description
displayName YES String Display name

Response Body

Name Type Description
user object Updated user object
└ userId long Unique user ID
└ address string User's wallet address
└ status integer User status (1 = active)
└ userType integer User type
└ userClass integer User class
└ displayName string User's display name
└ payoutAddress string User's payout address
└ locked boolean Whether the user has locked their account
└ collateralPerSlot string Collateral per slot amount
└ onchainPayout boolean Whether on-chain payout is enabled
└ accounts object[] List of user accounts
└└ accountId long Unique account ID
└└ userId long User ID associated with the account
└└ type integer Account type
└└ name string Account name
└└ status integer Account status
└└ updateDate long Last update timestamp in milliseconds

Error Codes

Code Description
USER_LOCKED User account is locked

POST /api/v1/user/lock

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/lock"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/lock"

headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {}
}

Permanently lock the authenticated user. This cannot be undone through the API. After lock, login, trading, deposits, and reads still work. The following user updates are rejected with USER_LOCKED:

To unlock an account, contact ETHGas. Unlock is not available in the API.

Request

No parameters required.

Response Body

Name Type Description
success boolean Operation success status

POST /api/v1/user/payoutAddress

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/payoutAddress?payoutAddress=0x1234567890123456789012345678901234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/payoutAddress"

payload = {
    'payoutAddress': '0x1234567890123456789012345678901234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {}
}

Update user payout address.

Fails with USER_LOCKED if the user has locked their account.

Request

Parameter Required Type Description
payoutAddress YES String New payout address (hex format)

Response Body

Name Type Description
success boolean Operation success status

Error Codes

Code Description
USER_LOCKED User account is locked

GET /api/v1/user/info

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/info"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/info"

payload = {}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "user": {
            "userId": 73,
            "address": "0xcc8f16b4e20feb0e7eb5a4725451db6316afa8f",
            "status": 1,
            "userType": 1,
            "userClass": 1,
            "displayName": "XXXXX",
            "payoutAddress": "0xde88f16b4e20feb0525289041db6316afa8f",
            "locked": false,
            "collateralPerSlot": "0",
            "onchainPayout": true,
            "accounts": [
                {
                    "accountId": 2170,
                    "userId": 73,
                    "type": 1,
                    "name": "Current",
                    "status": 1,
                    "updateDate": 1751854737000
                },
                {
                    "accountId": 2171,
                    "userId": 73,
                    "type": 2,
                    "name": "InPreconf",
                    "status": 1,
                    "updateDate": 1751854737000
                }
            ]
        }
    }
}

Get user information.

Request

No parameters required.

Response Body

Name Type Description
user object User object
└ userId long Unique user ID
└ address string User's wallet address
└ status integer User status (1 = active)
└ userType integer User type
└ userClass integer User class
└ displayName string User's display name
└ payoutAddress string User's payout address
└ locked boolean Whether the user has locked their account
└ collateralPerSlot string Collateral per slot amount
└ onchainPayout boolean Whether on-chain payout is enabled
└ accounts object[] List of user accounts
└└ accountId long Unique account ID
└└ userId long User ID associated with the account
└└ type integer Account type
└└ name string Account name
└└ status integer Account status
└└ updateDate long Last update timestamp in milliseconds

Account

GET /api/v1/user/accounts

Code sample:

curl  -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/accounts"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/accounts"

headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "accounts": [
            {
                "accountId": 127,
                "userId": 31,
                "type": 1,
                "name": "Current",
                "status": 1,
                "updateDate": 1672903708000,
                "tokens": [
                    {
                        "accountId": 127,
                        "tokenId": 1,
                        "quantity": "0.01",
                        "lockedQuantity": "0",
                        "code": "ETH",
                        "availableQuantity": "0.01"
                    }
                ]
            },
            {
                "accountId": 128,
                "userId": 31,
                "type": 2,
                "name": "Preconf Account",
                "status": 1,
                "updateDate": 1697445293000,
                "tokens": [
                    {
                        "accountId": 128,
                        "tokenId": 1,
                        "quantity": "9999993311.535880667",
                        "lockedQuantity": "1.5628",
                        "code": "ETH",
                        "availableQuantity": "9999993309.973080667"
                    }
                ]
            }
        ]
    }
}

Get list of user accounts.

Request

No parameters for this endpoint.

Response Body

Name Type Description
accounts arrary of object List of account objects
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ userId integer Unique ID for the user, assigned by ETHGas
└ type integer Account type:

1 for current account
2 for preconf trading account
└ name string Account name

Default values are "Current" and "Trading"
└ status integer Account status:

All active accounts have status 1
└ updateDate integer Datetime (Unix epoch milliseconds) the healthscoare and other risk metrics (asset amount, liability amount, etc) were last calculated
└ tokens object[] List of tokens in account
 └ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
 └ tokenId integer ETHGas Token ID

See Token IDs section for list of Token IDs
 └ quantity string Amount of token in account in USD
 └ lockedQuantity string Amount of token in account in USD which is covering pending limit orders (and so cannot be transfered out of account)
 └ code string Token code

See Token IDs section for list of token codes
 └ tokenType integer Token type:

Currently all tokens at ETHGas are designated as type 1
 └ valueType integer Value type:

1 for non-stablecoin tokens
2 for stablecoin tokens
 └ tokenValuationProtocol integer Platform the complex token comes from (if relevant):
 └ availableQuantity string Available quantity for using as collateral for buying or for transfering out of the account:

Available Quantity = Quantity - Locked Quantity

GET /api/v1/user/account/{id}

Code sample:

curl  -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/account/128"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/account/128"


headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "account": {
            "accountId": 128,
            "userId": 31,
            "type": 2,
            "name": "Trading",
            "status": 1,
            "updateDate": 1697445293000,
            "tokens": [
                {
                    "accountId": 128,
                    "tokenId": 1,
                    "quantity": "9999993308.004503191",
                    "lockedQuantity": "0",
                    "code": "ETH",
                    "tokenType": 1,
                    "valueType": 1,
                    "tokenValuationProtocol": 0,
                    "availableQuantity": "9999993308.004503191"
                }
            ]
        }
    }
}

Get account details for a given account ID.

Request

Parameter Required Type Description
id YES integer Account ID

Response Body

Name Type Description
account object Account object
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ userId integer Unique ID for the user, assigned by ETHGas
└ type integer Account type:

1 for current account
2 for trading account
└ name string Account name

Default values are "Current" and "Trading".
└ status integer Account status:

All active accounts have status 1
└ updateDate integer Datetime (Unix epoch milliseconds) the healthscoare and other risk metrics (asset amount, liability amount, etc) were last calculated.
└ tokens object[] List of tokens in account
 └ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
 └ tokenId integer ETHGas Token ID

See Token IDs section for list of Token IDs
 └ quantity string Amount of token in account in USD
 └ lockedQuantity string Amount of token in account in USD which is covering pending limit orders (and so cannot be transfered out of account)
 └ code string Token code

See Token IDs section for list of token codes
 └ tokenType integer Token type:

Currently all tokens at ETHGas are designated as type 1
 └ valueType integer Value type:

1 for non-stablecoin tokens
2 for stablecoin tokens
 └ tokenValuationProtocol integer Platform the complex token comes from (if relevant):
 └ availableQuantity string Available quantity for using as collateral for buying or for transfering out of the account:

Available Quantity = Quantity - Locked Quantity

GET /api/v1/user/account/{id}/txs

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/account/128/txs"
import requests

account_id = 128
url = "https://prod-mainnet.ethgas.com/api/v1/user/account/{account_id}/txs"


headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "txs": [
            {
                "trxId": 507873974,
                "accountId": 128,
                "tokenId": 1,
                "type": 15,
                "quantity": "-0.141865",
                "balance": "10010502890.372428552",
                "createDate": 1697450286000
            },
            {
                "trxId": 507873973,
                "accountId": 128,
                "tokenId": 1,
                "type": 2,
                "quantity": "-1418.65",
                "balance": "10010502890.514293552",
                "createDate": 1697450286000
            },
            {
                "trxId": 507873970,
                "accountId": 128,
                "tokenId": 1,
                "type": 15,
                "quantity": "-0.00009848",
                "balance": "9999993308.350858416",
                "createDate": 1697450286000
            },
            {
                "trxId": 507873969,
                "accountId": 128,
                "tokenId": 1,
                "type": 2,
                "quantity": "-0.9848",
                "balance": "9999993308.350956896",
                "createDate": 1697450286000
            },
            {
                "trxId": 507873966,
                "accountId": 128,
                "tokenId": 1,
                "type": 15,
                "quantity": "-0.00008252",
                "balance": "9999993309.335674376",
                "createDate": 1697450286000
            },
            {
                "trxId": 507873965,
                "accountId": 128,
                "tokenId": 1,
                "type": 2,
                "quantity": "0.8252",
                "balance": "9999993309.335756896",
                "createDate": 1697450286000
            }
        ]
    }
}

Get account transactions for a given account ID.

Request

This is an authenticated endpoint. Include Authorization: Bearer {{access_token}}.

Parameter Required Type Description
id YES integer Account ID
type NO string Transaction type (comma-separated for multiple types)
startId NO integer Start of transaction ID
limit NO integer Max number of transactions to return

Response Body

Name Type Description
txs object[] List of transaction objects
└ trxId integer Unique ID for the transaction, assigned by ETHGas
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ tokenId integer ETHGas Token ID

See Token IDs section for list of Token IDs
└ type integer Transaction type

See Transaction Types section for full list
└ quantity string Transaction quantity
└ balance string Balance of account after transaction
└ createDate integer Transaction datetime stamp (in UNIX time)

GET /api/v1/user/account/txs

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/account/txs"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/account/txs"

headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "txs": [
            {
                "trxId": 507873974,
                "accountId": 128,
                "tokenId": 1,
                "type": 15,
                "quantity": "-0.141865",
                "balance": "10010502890.372428552",
                "createDate": 1697450286000
            }
        ]
    }
}

Get account transactions for the current user.

Request

This is an authenticated endpoint. Include Authorization: Bearer {{access_token}}.

Parameter Required Type Description
type NO string Transaction type (comma-separated for multiple types)
startId NO integer Start of transaction ID
limit NO integer Max number of transactions to return (default: 20, max: 100)

Response Body

Name Type Description
txs object[] List of transaction objects
└ trxId integer Unique ID for the transaction, assigned by ETHGas
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ tokenId integer ETHGas Token ID

See Token IDs section for list of Token IDs
└ type integer Transaction type

See Transaction Types section for full list
└ quantity string Transaction quantity
└ balance string Balance of account after transaction
└ createDate integer Transaction datetime stamp (in UNIX time)

GET /api/v1/user/account/trxs

Unified account-related activity for the current user (trade, deposit, withdraw, transfer, slashing categories). Unrecognized category values return a SYSTEM_VALIDATION error.

Request

Authenticated. Query parameters:

Parameter Required Type Description
categories NO string Comma-separated categories (preferred). Same semantics as category when both are used—categories wins if non-blank.
category NO string One category. When categories is also set, categories is used.
startId NO long Pagination cursor
limit NO integer Page size (default 50, max 1000)

Response Body

Name Type Description
accountTrxs object[] List of transaction/activity records across the requested categories

POST /api/v1/user/account/transfer/token

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/account/transfer/token?fromAccountId=128&toAccountId=127&tokenId=1&quantity=0.01"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/account/transfer/token"

params = {
    "fromAccountId": 128,
    "toAccountId": 127,
    "tokenId": 1,
    "quantity": 0.01
}

headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {}
}

Transfer token between accounts.

Request

Parameter Required Type Description
fromAccountId YES integer Source account ID
toAccountId YES integer Destination account ID
tokenId YES integer Token ID
quantity YES number Quantity

Response Body

Name Type Description

Funding

GET /api/v1/p/funding/contractAddress

Code sample:

curl -X  GET "$ETHGAS_BASE_URL/api/v1/p/funding/contractAddress"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/funding/contractAddress"


response = requests.get(url)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "contractAddress": "0x818EF032D736B1a2ECC8556Fc1bC65aEBD8482c5"
    }
}

Get deposit collateral address.

Request

Parameter Required Type Description

Response Body

Name Type Description
contractAddress string deposit collateral address 0x818EF032D736B1a2ECC8556Fc1bC65aEBD8482c5

GET /api/v1/user/funding/deposits

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X  GET "$ETHGAS_BASE_URL/api/v1/user/funding/deposits"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/funding/deposits"

payload = {}
headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "deposits": [
            {
                "eventId": 6,
                "chainId": 1,
                "blockIdx": 123456,
                "blockHash": "0xdd5a8e1742e26ce90feb865f1c6a0fdbf2d8cbed086314fc85281ff47aaea5ee",
                "transactionIdx": 2,
                "transactionHash": "0x866bb046a97243519679183e08e5ce6728d3e1e9976a2535ce8c8887b62997a2",
                "logIdx": 2,
                "senderAddress": "0xd055335192d920ce2de4a88557f232943a901a9f",
                "depositAddress": "0xd055335192d920ce2de4a88557f232943a901a9f",
                "status": 10,
                "deposits": [
                    {
                        "a": "0xdc0b8e3cd3fec447940cb8107957f22e7e320812",
                        "q": 500000000000000000,
                        "s": 10
                    }
                ],
                "actions": [],
                "createDate": 1746005076000
            }
        ]
    }
}

Get fund deposits history.

Request

Parameter Required Type Description
limit NO integer Maximum number of deposits to return
startBlockId NO integer Block start ID

Response Body

Name Type Description
deposits object[] List of deposits
└ eventId long Unique ID for the deposit event
└ chainId integer Unique ID for the chain, assigned by ETHGas:

Currently only Ethereum (Chain ID 1) is supported.
└ blockIdx long Block ID
└ blockHash byte[] Block hash
└ transactionIdx long Transaction ID
└ transactionHash byte[] Transaction hash
└ logIdx integer Log ID
└ senderAddress string Sender address
└ depositAddress string Deposit address
└ status integer Deposit status, success = 10
└ deposits object[] Deposits
└ actions string Actions
└ createDate date create date

Deposit history is owner-only and remains scoped to the authenticated user’s wallet. Optional accountId must belong to that user; a shared read grant does not authorize deposit history and returns COMMON_NO_ACCOUNT. Omission reads the current user’s wallet history. Lists default to 20 rows and cap at 1000; send a positive limit.

POST /api/v1/user/funding/withdraw

Code sample:

curl -X POST "$ETHGAS_BASE_URL/api/v1/user/funding/withdraw"

[
    {
        "accountId": 12,
        "tokenId": 1,
        "chainId": 1,
        "quantity": "0.05"
    },
    {
        "accountId": 12,
        "tokenId": 2,
        "chainId": 1,
        "quantity": "0.001"
    }
]
import requests
import json

url = "https://prod-mainnet.ethgas.com/api/v1/user/funding/withdraw"

payload = json.dumps([
    {
        "accountId": 12,
        "tokenId": 1,
        "chainId": 1,
        "quantity": "0.05"
    }
])

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, data=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "submittedRequestIds": [
            4
        ],
        "failedRequests": [
            {
                "accountId": 21,
                "tokenId": 1,
                "chainId": 32382,
                "quantity": "0.001",
                "status": 101,
                "remark": "Unsupported Chain ID."
            }
        ]
    }
}

Request to withdraw funds.

Fails with USER_LOCKED if the user has locked their account.

Request

Parameter Required Type Description
requests YES object[] List of withdraw requests
└ accountId YES integer Account ID
└ chainId YES integer Chain ID
└ tokenId YES integer Token ID
└ quantity YES string Quantity to be withdrawn

Response Body

Name Type Description
submittedRequestIds integer[] List of successful submitted request IDs
failedRequests object[] List of failed submitted requests with reason.
└ accountId integer Account ID
└ chainId integer Chain ID
└ tokenId integer Token ID
└ fee string Token ID
└ quantity string Quantity to be withdrawn
└ status integer Status of submitted withdraw request
└ remark string Reason of failed request.

Error Codes

Code Description
USER_LOCKED User account is locked

Withdrawal acceptance and settlement

Send a JSON array. Each item contains accountId, tokenId, chainId, and quantity. ETH is tokenId 1 on the chain for your environment. quantity is a positive decimal string and must be greater than the withdrawal fee. The amount credited is quantity minus the fee.

success true can still include both submittedRequestIds and failedRequests. A submitted request is not yet settled on chain. Check both lists, then call withdrawal status for the accepted IDs. After a timeout, look up the IDs you already sent before submitting the batch again.

The daily limit is a rolling 24-hour total for the token and network.

Status Meaning
0 Engine submitted.
1 Pending withdrawal.
2 Submitted to blockchain.
10 Successful.
11 Insufficient funds.
12 Insufficient on-chain balance.
99 On-chain failure.
100 Canceled.
101 Rejected.

GET /api/v1/p/funding/withdraw/dailyWithdrawLimits

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/funding/withdraw/dailyWithdrawLimits"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/funding/withdraw/dailyWithdrawLimits"

response = requests.get(url)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "dailyWithdrawLimits": [
            {
                "tokenId": 1,
                "chainId": 1,
                "tokenAddress": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
                "withdrawFee": "0.01",
                "dailyWithdrawLimit": "50",
                "remainingWithdrawLimit": "49.863"
            }
        ]
    }
}

Get list of token's current on-chain daily withdraw limits

Request

Parameter Required Type Description

Response Body

Name Type Description
Name Type Description
----------------------------- --------- --------------------------------------------------------------------------------------------------------------------------------------------
dailyWithdrawLimits object[] Block chain details
└ tokenId integer Unique ID for the blockchain network assigned by ETHGas, assigned by ETHGas:

Currently only Ethereum (Chain ID 1) is supported.
└ chainId integer Unique ID for the chain:

Currently only Ethereum (Chain ID 1) is supported.
└ tokenAddress string Address of ERC-20 token contract (e.g. WETH)
└ withdrawFee string Withdrawal fee.
└ dailyWithdrawLimit string Daily withdraw limit of ERC-20 token
└ remainingWithdrawLimit integer remaining withdraw limit in past 24 hours.

GET /api/v1/user/funding/withdraw/status

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/funding/withdraw/status?requestIds=123%2c456"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/funding/withdraw/status?requestIds=123,456"

params = {
    'requestIds': '123,456'
}

headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "requests": [
            {
                "requestId": 16,
                "userId": 17,
                "accountId": 15,
                "tokenId": 1,
                "chainId": 17000,
                "quantity": "0.005",
                "fee": "0.001",
                "status": 10,
                "txHash": "0x4de9ecf18ea11d8d290a01e759f3b150809f70cccb08bb74ceede7a801e2e9a5",
                "createDate": 1746161880000,
                "updateDate": 1746162105000
            },
            {
                "requestId": 15,
                "userId": 17,
                "accountId": 15,
                "tokenId": 1,
                "chainId": 17000,
                "quantity": "0.005",
                "fee": "0.001",
                "status": 10,
                "txHash": "0xba85584d93dd7a209838308a767c9848535d0ada4f83c17526147f9c74104edd",
                "createDate": 1746160279000,
                "updateDate": 1746160538000
            }
        ]
    }
}

Get fund withdrawal request status (for given list of request IDs).

Request

Parameter Required Type Description
requestIds YES integer[] List of fund withdrawal request IDs

Response Body

Name Type Description
requests object[] List of withdraw requests with status
└ requestId integer Request ID
└ userId integer User ID
└ accountId integer Account ID
└ chainId integer Chain ID
└ tokenId integer Token ID
└ fee string Token ID
└ quantity string Quantity to be withdrawn
└ status integer Status of submitted withdraw request
└ quantity string Quantity to be withdrawn
└ txHash string Transaction hash of submitted withdraw transaction
└ createDate string Create date
└ updateDate string Last update date

Optional accountId (integer) requires ownership/shared-read authorization and filters requested withdrawal IDs strictly to that account. IDs belonging to another account are omitted. Without accountId, only requests belonging to the authenticated user are returned.

GET /api/v1/user/funding/withdraws

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/funding/withdraws"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/funding/withdraws"

headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "requests": [
            {
                "requestId": 16,
                "userId": 17,
                "accountId": 15,
                "tokenId": 1,
                "chainId": 17000,
                "quantity": "0.005",
                "fee": "0.001",
                "status": 10,
                "txHash": "0x4de9ecf18ea11d8d290a01e759f3b150809f70cccb08bb74ceede7a801e2e9a5",
                "createDate": 1746161880000,
                "updateDate": 1746162105000
            },
            {
                "requestId": 15,
                "userId": 17,
                "accountId": 15,
                "tokenId": 1,
                "chainId": 17000,
                "quantity": "0.005",
                "fee": "0.001",
                "status": 10,
                "txHash": "0xba85584d93dd7a209838308a767c9848535d0ada4f83c17526147f9c74104edd",
                "createDate": 1746160279000,
                "updateDate": 1746160538000
            }
        ]
    }
}

Get list of fund withdrawals.

Request

Parameter Required Type Description
limit NO integer Maximum number of withdrawals to return
startId NO integer Fund withdrawal request start ID

Response Body

Name Type Description
requests object[] List of withdraw requests
└ requestId integer Request ID
└ userId integer User ID
└ accountId integer Account ID
└ chainId integer Chain ID
└ tokenId integer Token ID
└ fee string Token ID
└ quantity string Quantity to be withdrawn
└ status integer Status of submitted withdraw request
└ quantity string Quantity to be withdrawn
└ txHash string Transaction hash of submitted withdraw transaction
└ createDate string Create date
└ updateDate string Last update date

Optional accountId (integer) filters results strictly to that account after ownership/shared-read authorization. No sibling-account records are included. Omission returns only the current user’s own withdrawal history. Lists default to 20 rows and cap at 1000; send a positive limit.

Network

GET /api/v1/p/network

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/network"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/network"

params = {
    'chainId': 1
}

headers = {}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "network": {
            "networkId": 1,
            "chainId": 11155111,
            "name": "Ethereum",
            "enable": true,
            "visible": true
        }
    }
}

Get network details for a given blockchain ID.

Request

Parameter Required Type Description
chainId YES integer Chain ID

Response Body

Name Type Description
network object Block chain details
└ networkId integer Unique ID for the blockchain network assigned by ETHGas, assigned by ETHGas:

Currently only Ethereum (Chain ID 1) is supported.
└ chainId integer Unique ID for the chain:

Currently only Ethereum (Chain ID 1) is supported.
└ name string Name of the blockchain network (e.g. Ethereum)
└ enable boolean Whether this chain is enabled within ETHGas:

This should always return true.
└ visible boolean Whether this chain is visible on ETHGas:

This should always return true.

Tokens

GET /api/v1/p/tokens

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/tokens"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/tokens"

headers = {}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "tokens": [
            {
                "tokenId": 1,
                "code": "ETH",
                "name": "Wrapped ETH",
                "tokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
                "decimals": 18,
                "nativeToken": false,
                "withdrawFee": "0.01",
                "price": "1582.09761118"
            }
        ]
    }
}

Get details for all tokens.

Request

No parameters for this endpoint.

Response Body

Name Type Description
tokens object[] List of token objects
└ tokenId integer ETHGas Token ID

See Token IDs section for list of Token IDs
└ code string Token code

See Token IDs section for list of token codes
└ name string Token code

See Token IDs section for list of token names
└ tokenAddress string Token chain address
└ decimals integer Number of decimal precision for this token
└ withdrawFee string Withdrawal fee (in number of tokens)
└ price string Latest token price

Fees

GET /api/v1/p/user/fees

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/user/fees"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/user/fees"

headers = {}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "buyFeeRate": "0.01",
        "primarySellFeeRate": "0.045", 
        "secondarySellFeeRate": "0.05"
    }
}

Get current trading fees

Request

Parameter Required Type Description

Response Body

Name Type Description
buyFeeRate BigDecimal Percentage fees charged for buy transaction
primarySellFeeRate BigDecimal Percentage fees charged for first time sell transaction
secondarySellFeeRate BigDecimal Percentage fees charged for subsequent sell transaction

Whole Block Markets

GET /api/v1/p/wholeblock/markets

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/wholeblock/markets"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/wholeblock/markets"

headers = {}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "markets": [
            {
                "marketId": 2000000295209,
                "slot": 295209,
                "instrumentId": "ETH-WB-295209",
                "name": "ETH Whole Block Slot #295209",
                "priceStep": "0.00000000001",
                "minPrice": "0.00000000001",
                "maxPrice": "0.00001",
                "bestBid": "0.00000000540",
                "availablePreconf": 17257755,
                "direction": true,
                "price": "0.00000000588",
                "midPrice": "0.00000000564",
                "status": 1,
                "maturityTime": 1751947307000,
                "blockTime": 1751947311000,
                "finalityTime": 1751948079000,
                "ofac": false,
                "realtime": false,
                "tradingEnabled": true,
                "mode": 0,
                "multiRelay": true,
                "updateDate": 1751947297000
            },
            {
                "marketId": 2000000295211,
                "slot": 295211,
                "instrumentId": "ETH-WB-295211",
                "name": "ETH Whole Block Slot #295211",
                "priceStep": "0.00000000001",
                "minPrice": "0.00000000001",
                "maxPrice": "0.00001",
                "availablePreconf": 16587826,
                "direction": true,
                "price": "0.00000000581",
                "midPrice": "0.00000000580",
                "status": 1,
                "maturityTime": 1751947331000,
                "blockTime": 1751947335000,
                "finalityTime": 1751948103000,
                "ofac": false,
                "realtime": true,
                "tradingEnabled": true,
                "mode": 0,
                "multiRelay": false,
                "updateDate": 1751947297000
            }
        ]
    }
}

Get active all whole block market details.

Request

Parameter Required Type Description

Response Body

Name Type Description
markets object[] List of Whole Block Market objects
└ marketId integer Whole block market ID
└ slot integer Slot number of the block
└ instrumentId string Whole block market instrument ID

Use endpoint [GET /api/v1/p/wholeblock/markets] to get a list of all available wholeblock markets' instrument IDs
└ name string Whole block market display name

In format: "ETH Whole Block Slot #<slot>"
└ priceStep string Minimum increment between valid price levels
└ minPrice string Minimum price
└ maxPrice string Maximum price
└ bestBid string Current best bid price on the market
└ availablePreconf integer Available preconf quantity for trading
└ direction boolean The last trading direction (true = buy, false = sell)
└ price string Latest traded market price for this market
└ midPrice string Mid price derived from the current market quote
└ status integer Market status - see the Market Status Codes section for more information
└ maturityTime integer Datetime (Unix epoch milliseconds) when the market will be closed
└ blockTime integer Datetime (Unix epoch milliseconds) when the block starts
└ finalityTime integer Datetime (Unix epoch milliseconds) when the block is being finalized
└ ofac boolean Whether the market is flagged for OFAC-compliant builder routing
└ realtime boolean Whether the market is running in realtime mode
└ tradingEnabled boolean Whether trading is currently enabled for this market
└ mode integer Mode when the market was created. 0 is max-profit. 1 is light mode.
└ multiRelay boolean Whether this market is configured to use multi-relay
└ updateDate integer Datetime (Unix epoch milliseconds) when the market orderbook was last updated

GET /api/v1/p/wholeblock/market

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/wholeblock/market?slot=295209"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/wholeblock/market"

params = {"slot": 295209}

response = requests.get(url, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "markets": {
            "marketId": 2000000295209,
            "slot": 295209,
            "instrumentId": "ETH-WB-295209",
            "name": "ETH Whole Block Slot #295209",
            "priceStep": "0.00000000001",
            "minPrice": "0.00000000001",
            "maxPrice": "0.00001",
            "bestBid": "0.00000000540",
            "availablePreconf": 17257755,
            "direction": true,
            "price": "0.00000000588",
            "midPrice": "0.00000000564",
            "status": 1,
            "maturityTime": 1751947307000,
            "blockTime": 1751947311000,
            "finalityTime": 1751948079000,
            "ofac": false,
            "realtime": false,
            "tradingEnabled": true,
            "mode": 0,
            "multiRelay": true,
            "updateDate": 1751947297000
        }
    }
}

Get whole block market details for a specific slot.

Request

Parameter Required Type Description
slot YES integer Slot number of the block

Response Body

Name Type Description
markets object Whole Block Market object (same shape as an entry in GET /api/v1/p/wholeblock/markets)

GET /api/v1/p/wholeblock/positions

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/wholeblock/positions?instrumentId=ETH-WB-9884031&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/wholeblock/positions"

params = {
  "instrumentId": "ETH-WB-9884031",
  "limit": 10
}

response = requests.get(url, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "positions": [
              {
                "slot": 296895,
                "quantity": "1",
                "locked": "0",
                "expired": false,
                "updateDate": 1751967044730,
                "available": "1",
                "averagePrice": "0.0000000058"
            }
        ]
    }
}

Get whole block positions.

Request

Parameter Required Type Description
instrumentId NO string Instrument ID
limit NO integer Maximum Number of Positions To Return (default: 10)

Response Body

Name Type Description
positions object[] List of position object
└ slot integer Slot number of the block
└ quantity string Position quantity
└ available string Position quantity available for trading
└ locked string Locked quantity
└ expired boolean Position expired or not
└ averagePrice string Average price of executed trades
└ updateDate integer Datetime (Unix epoch milliseconds) when the order was last updated

GET /api/v1/p/wholeblock/orders

See pagination: omit startId for the first page in either direction. Supplied cursors are exclusive. done=true selects only status 10.

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/wholeblock/orders?instrumentId=ETH-WB-9884031&onbook=false&done=false&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/wholeblock/orders"

params = {
  "instrumentId": "ETH-WB-9884031",
  "onbook": False,
  "done": False,
  "limit": 10
}

response = requests.get(url, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "orders": [
             {
                "orderId": 8522999,
                "marketId": 2000000160031,
                "side": false,
                "orderType": 2,
                "quantity": "1",
                "fulfilled": "1",
                "price": "0.00000000569",
                "fees": "0.0091793925",
                "status": 10,
                "clientOrderId": "b0eeb664",
                "passive": false,
                "createDate": 1750324420793,
                "source": 1,
                "updateDate": 1750324423349,
                "instrumentId": "ETH-WB-160031"
            },
            {
                "orderId": 8523033,
                "marketId": 2000000160031,
                "side": true,
                "orderType": 2,
                "quantity": "1",
                "fulfilled": "1",
                "price": "0.00000000591",
                "fees": "0.002039865",
                "status": 10,
                "clientOrderId": "b274e878",
                "passive": false,
                "createDate": 1750324423349,
                "source": 1,
                "updateDate": 1750324423349,
                "instrumentId": "ETH-WB-160031"
            }
        ]
    }
}

Get whole block orders.

Request

Parameter Required Type Description
instrumentId YES string List whole block Orders for a market
onbook NO boolean Pending Orders Only? (default: false)
done NO boolean Done Orders Only? (default: false)
startId NO integer Exclusive order cursor; omitted for the first page
asc NO boolean Sort Order Direction, true=asc, false=desc, Default to true=asc
limit NO integer Maximum number of orders to return (default: 10; must be positive; cap: 1000)

Response Body

Name Type Description
orders object[] List of order object
└ orderId integer Unique order ID, assigned by ETHGas
└ marketId integer Market ID for this order
└ instrumentId string Whole block market instrument ID
└ side boolean buy order (true) or sell order (false)
└ orderType integer Market (1), limit (2), or FOK (3)
└ quantity string Order quantity (1 for whole block orders)
└ fulfilled string Quantity that has already been executed
└ price string Price of the order
└ fees string Fees charged for this order
└ status integer Order status - see the Order Status Codes section for more information
└ errorCode integer Error code if order failed (omitted if absent)
└ clientOrderId string Client order ID: 1–32 ASCII letters/digits, matching ^[a-zA-Z0-9]{1,32}$
└ passive boolean Whether the order is a maker order only
└ createDate integer Datetime (Unix epoch milliseconds) when the order was created
└ source integer Where the order is originated
└ updateDate integer Datetime (Unix epoch milliseconds) when the order was last updated

GET /api/v1/p/wholeblock/trades

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/wholeblock/trades?instrumentId=ETH-WB-9884031&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/wholeblock/trades"

params = {
  "instrumentId": "ETH-WB-9884031",
  "limit": 10
}

response = requests.get(url, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "trades": [
            {
                "instrumentId": "ETH-WB-9884031",
                "trxId": 11675386,
                "side": false,
                "price": "0.00000002",
                "quantity": "1",
                "preconfQuantity": "320000000",
                "date": 1730269305359
            },
            {
                "instrumentId": "ETH-WB-9884031",
                "trxId": 2146182,
                "side": false,
                "price": "0.00000000568",
                "quantity": "1",
                "preconfQuantity": "19005872",
                "date": 1750299601863
            }
        ]
    }
}

Get whole block trades.

Request

Parameter Required Type Description
instrumentId YES string List whole block trades for a market
limit NO integer Maximum Number of Trades To Return (default: 10)

Response Body

Name Type Description
trades object[] List of trades
└ instrumentId string Whole block market instrument ID
└ trxId integer Transaction Id
└ side boolean Order Side. Buy = true, Sell = false
└ price string Latest traded market price for this market
└ quantity string Quantity always = 1
└ preconfQuantity string Preconf quantity sold with the whole block
└ date integer Datetime (Unix epoch milliseconds) when the trade was executed

Inclusion Preconf Markets

GET /api/v1/p/inclusion-preconf/markets

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/inclusion-preconf/markets"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/inclusion-preconf/markets"

headers = {}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "markets": [
           {
                "marketId": 1000000295045,
                "slot": 295045,
                "instrumentId": "ETH-PC-295045",
                "name": "Eth Preconf Inclusion Slot #295045",
                "quantityStep": "1",
                "minQuantity": "1",
                "maxQuantity": "35850000",
                "priceStep": "0.00000000001",
                "minPrice": "0.00000000001",
                "maxPrice": "0.00001",
                "bestBid": "0.00000000015",
                "totalPreconf": 35850000,
                "availablePreconf": 19678280,
                "direction": true,
                "price": "0.00000000002",
                "midPrice": "0.00000000015",
                "status": 1,
                "maturityTime": 1751945339000,
                "trxSubmitTime": 1751945341000,
                "blockTime": 1751945343000,
                "finalityTime": 1751946111000,
                "totalGas": 16171720,
                "validatorType": 0,
                "mode": 0,
                "updateDate": 1751945326000
            },
            {
                "marketId": 1000002880222,
                "slot": 2880222,
                "instrumentId": "ETH-PC-2880222",
                "name": "Eth Preconf Inclusion Slot #2880222",
                "quantityStep": "1",
                "minQuantity": "1",
                "maxQuantity": "30000000",
                "priceStep": "0.00000000001",
                "minPrice": "0.00000000001",
                "maxPrice": "0.00001",
                "collateralPerSlot": "2",
                "totalPreconf": 36000000,
                "availablePreconf": 36000000,
                "direction": true,
                "price": "0.00000001256",
                "midPrice": "0.00000001256",
                "status": 1,
                "maturityTime": 1730465060000,
                "trxSubmitTime": 1730465062000,
                "blockTime": 1730465064000,
                "finalityTime": 1730465832000,
                "totalGas": 29952852,
                "validatorType": 0,
                "mode": 0,
                "updateDate": 1730465041000
            }
        ]
    }
}

Get active all preconf market details.

Request

Parameter Required Type Description

Response Body

Name Type Description
markets object[] List of Market objects
└ marketId integer Preconf market ID
└ slot integer Slot number of the block
└ instrumentId string Inclusion Preconf Market instrument ID

Use endpoint [GET /api/v1/p/inclusion-preconf/markets] to get a list of all available inclusion preconf markets' instrument IDs
└ name string Preconf market name

In format: "ETH-PC-xxxxxx"
└ quantityStep string Minimum increment between different order quantities
└ minQuantity string Minimum order quantity
└ maxQuantity string Maximum order quantity
└ priceStep string Minimum increment between valid price levels
└ minPrice string Minimum price
└ maxPrice string Maximum price
└ collateralPerSlot string ETH reserved by validator as collateral for this slot
└ totalPreconf integer Total preconf quantity for this slot
└ availablePreconf integer Available preconf quantity for trading
└ direction boolean The last trading direction (true = buy, false = sell)
└ price string Latest traded market price for this market
└ midPrice string Mid price of bid and ask
└ status integer Market status - see the Market Status Codes section for more information
└ maturityTime integer Datetime (Unix epoch milliseconds) when the market will be closed
└ trxSubmitTime integer Datetime (Unix epoch milliseconds) when the market will be closed for submitting transactions
└ blockTime integer Datetime (Unix epoch milliseconds) when the block starts
└ finalityTime integer Datetime (Unix epoch milliseconds) when the block is being finalized
└ totalGas integer Total gas available for sale in this block
└ validatorType integer Type of validator (0 for normal validators, 1 for SSV validators)
└ mode integer Mode when the market was created. 0 is max-profit. 1 is light mode.
└ updateDate integer Datetime (Unix epoch milliseconds) when the market orderbook was last updated

GET /api/v1/p/inclusion-preconf/market

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/inclusion-preconf/market?slot=2880221"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/inclusion-preconf/market"

params = {
    "slot": 2880221
}

headers = {}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "market": {
            "marketId": 1000002880221,
            "slot": 2880221,
            "instrumentId": "ETH-PC-2880221",
            "name": "Eth Preconf Inclusion Slot #2880221",
            "quantityStep": "1",
            "minQuantity": "1",
            "maxQuantity": "30000000",
            "priceStep": "0.00000000001",
            "minPrice": "0.00000000001",
            "maxPrice": "0.00001",
            "collateralPerSlot": "3.996",
            "totalPreconf": 36000000,
            "availablePreconf": 30000000,
            "direction": true,
            "price": "0.00000001302",
            "midPrice": "0.00000001299",
            "status": 1,
            "maturityTime": 1730465048000,
            "trxSubmitTime": 1730465050000,
            "blockTime": 1730465052000,
            "finalityTime": 1730465820000,
            "totalGas": 29982469,
            "validatorType": 1,
            "mode": 0,
            "updateDate": 1730465042000
        }
    }
}

Get preconfs market details for a given slot

Request

Parameter Required Type Description
slot YES integer Slot number

Response Body

Name Type Description
market object Market object
└ marketId integer Preconf market ID
└ slot integer Slot number of the block
└ instrumentId string Inclusion Preconf Market instrument ID

Use endpoint [GET /api/v1/p/inclusion-preconf/markets] to get a list of all available instrument IDs
└ name string Preconf market name

In format: "ETH-PC-xxxxxx"
└ quantityStep string Minimum increment between different order quantities
└ minQuantity string Minimum order quantity
└ maxQuantity string Maximum order quantity
└ priceStep string Minimum increment between valid price levels
└ minPrice string Minimum price
└ maxPrice string Maximum price
└ collateralPerSlot string ETH reserved by validator as collateral for this slot
└ totalPreconf integer Total preconf quantity for this slot
└ availablePreconf integer Available preconf quantity for trading
└ direction boolean The last trading direction (true = buy, false = sell)
└ price string Latest traded market price for this market
└ midPrice string Mid price of bid and ask
└ status integer Market status - see the Market Status Codes section for more information
└ maturityTime integer Datetime (Unix epoch milliseconds) when the market will be closed
└ trxSubmitTime integer Datetime (Unix epoch milliseconds) when the market will be closed for submitting transactions
└ blockTime integer Datetime (Unix epoch milliseconds) when the block starts
└ finalityTime integer Datetime (Unix epoch milliseconds) when the block is being finalized
└ totalGas integer Total gas available for sale in this block
└ validatorType integer Type of validator (0 for normal validators, 1 for SSV validators)
└ mode integer Mode when the market was created. 0 is max-profit. 1 is light mode.
└ updateDate integer Datetime (Unix epoch milliseconds) when the market orderbook was last updated

GET /api/v1/p/inclusion-preconf/trades

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/inclusion-preconf/trades?instrumentId=ETH-PC-988403"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/inclusion-preconf/trades"

params = {
    "instrumentId": "ETH-PC-988403",
}

headers = {}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
    "trades": [
        {
            "trxId": "1231310314",
            "instrumentId": "ETH-PC-988403",
            "side": false,
            "price": "0.0501",
            "quantity": "210000",
            "date": 1689833397180
        },
        {
            "trxId": "1231310327",
            "instrumentId": "ETH-PC-988403",            
            "side": false,
            "price": "0.0493",
            "quantity": "400000",
            "date": 1689833043675
        },
        {
            "trxId": "1249310327",
            "instrumentId": "ETH-PC-988403",                        
            "side": true,
            "price": "0.0487",
            "quantity": "100000",
            "date": 1689832827936
        },
        {
            "trxId": "1252310327",
            "instrumentId": "ETH-PC-988403",                       
            "side": false,
            "price": "0.0478",
            "quantity": "350000",
            "date": 1689832426057
        },
        {
            "trxId": "1261310327",
            "instrumentId": "ETH-PC-988403",                        
            "side": false,
            "price": "0.0339",
            "quantity": "21000",
            "date": 1689799385952
        }
    ]
}

Get recent preconf trade details for a given preconf instrument ID.

Request

Parameter Required Type Description
instrumentId YES string Instrument ID
limit NO integer Maximum number of transactions to return

Response Body

Name Type Description
trades object[] List of trades
└ trxId string Transaction ID
└ instrumentId string Instrument ID
└ side integer Order Side. Buy = 1, Sell = 0
└ price string Latest traded market price for this market
└ quantity integer Quantity of the preconf bought
└ date integer Datetime (Unix epoch milliseconds) when the trade was executed

GET /api/v1/p/inclusion-preconf/positions

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/inclusion-preconf/positions?instrumentId=ETH-PC-475423&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/inclusion-preconf/positions"
params = {"instrumentId": "ETH-PC-475423", "limit": 10}

response = requests.get(url, params=params)
print(response.text)

Example response:

{
    "success": true,
    "data": {
        "positions": []
    }
}

Get Preconf positions.

Request

Parameter Required Type Description
instrumentId NO string Instrument ID
limit NO integer Maximum number of positions to return (default: 10; positive; cap: 1000)

Response Body

Name Type Description
positions object[] List of positions

GET /api/v1/p/inclusion-preconf/orders

See pagination: omit startId for the first page in either direction. Supplied cursors are exclusive. done=true selects only status 10.

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/inclusion-preconf/orders?instrumentId=ETH-PC-475423&onBook=false&done=false&startId=0&asc=true&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/inclusion-preconf/orders"
params = {
  "instrumentId": "ETH-PC-475423",
  "onBook": False,
  "done": False,
  "startId": 0,
  "asc": True,
  "limit": 10
}

response = requests.get(url, params=params)
print(response.text)

Example response:

{
    "success": true,
    "data": {
        "orders": []
    }
}

Get Preconf orders.

Request

Parameter Required Type Description
instrumentId YES string Instrument ID
onBook NO boolean Pending orders only (default: false)
done NO boolean Done orders only (default: false)
startId NO long Exclusive order cursor; omitted for the first page
asc NO boolean Sort direction, true=asc, false=desc (default: true)
limit NO integer Maximum number of orders to return (default: 10). Values must be positive; values above 1000 are capped at 1000.

Response Body

Name Type Description
orders object[] List of orders

GET /api/v1/p/inclusion-preconf/top-sales

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/inclusion-preconf/top-sales?instrumentId=ETH-PC-475423&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/inclusion-preconf/top-sales"

params = {
    "instrumentId": "ETH-PC-475423",
    "limit": 10
}

headers = {}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "positions": [
            {
                "positionId": 123456789,
                "instrumentId": "ETH-PC-475423",
                "quantity": "1000",
                "avgPrice": "0.0000000125",
                "status": "ACTIVE"
            }
        ]
    }
}

Get Preconf positions by price.

Request

Parameter Required Type Description
instrumentId NO String Instrument ID
limit NO Integer Maximum number of positions to return (default: 10)

Response Body

Name Type Description
positions object[] List of positions
└ positionId long Position ID
└ instrumentId string Instrument ID
└ quantity string Position quantity
└ avgPrice string Average price
└ status string Position status

Whole Block Trading

POST /api/v1/wholeblock/order

Requires bearer authentication and an application/json body.

Example request:

{
  "accountId": 128,
  "instrumentId": "ETH-WB-9884031",
  "side": true,
  "orderType": 2,
  "clientOrderId": "exampleOrder0001",
  "passive": false,
  "price": "0.00000000569"
}

Send a reviewed request.json containing the JSON body above. Set ETHGAS_BASE_URL and ETHGAS_ACCESS_TOKEN for your environment.

curl --request POST "$ETHGAS_BASE_URL/api/v1/wholeblock/order" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json
import json
import os
import requests

with open("request.json", encoding="utf-8") as request_file:
    payload = json.load(request_file)
response = requests.post(
    os.environ["ETHGAS_BASE_URL"].rstrip("/") + "/api/v1/wholeblock/order",
    headers={"Authorization": "Bearer " + os.environ["ETHGAS_ACCESS_TOKEN"]},
    json=payload,
    timeout=30,
)
# Check HTTP status and content type before interpreting the JSON envelope.
print(response.status_code, response.text)

Request Body

Parameter Required Type Description
accountId YES integer Trading/preconf account ID. Missing/zero is rejected.
instrumentId CONDITIONAL string Market instrument. Canonical selector; discover an active market first.
marketId CONDITIONAL integer (int64) Alternative market identifier. Supply one unambiguous market selector; do not send conflicting identifiers.
side YES boolean Buy true, sell false.
orderType YES integer 1 market, 2 limit, 3 fill-or-kill (FOK).
clientOrderId YES string 1–32 ASCII letters/digits; ^[a-zA-Z0-9]{1,32}$. Retain for reconciliation.
passive NO boolean Default false; post-only when true. FOK with passive=true is rejected.
price CONDITIONAL decimal string ETH per gas. Required and positive for limit/FOK; obey market min/max/step. For market orders, omit for a regular market order; a supplied price is a slippage limit.
quantity NO decimal string Server always sets quantity to 1, overriding any supplied value.

Send price and quantity as decimal strings, within the market minimum, maximum, and step. Omit response fields such as fees, fulfilled, status, and orderId.

Response Body

This response confirms that the order was accepted. It includes orderDate. Order lists use createDate and updateDate, and that is where you read fees and averageTradePrice. If the request sends only instrumentId, marketId can be 0. Read the market from the market list.

Field in data.order Type Description
orderId integer (int64) Assigned order ID.
accountId / instrumentId / side / orderType / passive / clientOrderId request types Submitted order parameters.
marketId integer (int64) May remain 0 for instrument-only requests.
quantity / fulfilled / price decimal string Quantity, executed quantity and submitted price; absent nullable fields may be omitted.
status integer See Order Status Codes; acknowledgement is not proof of full execution.
orderDate integer Order timestamp in epoch milliseconds.
source integer 1 for orders submitted through this REST path.
preconfQuantity integer Integer gas quantity.

Example response:

{
  "success": true,
  "data": {
    "order": {
      "accountId": 128,
      "instrumentId": "ETH-WB-9884031",
      "side": true,
      "orderType": 2,
      "clientOrderId": "exampleOrder0001",
      "passive": false,
      "price": "0.00000000569",
      "orderId": 204415806,
      "marketId": 0,
      "quantity": "1",
      "fulfilled": "0",
      "status": 1,
      "source": 1,
      "orderDate": 1790812800000
    }
  }
}

Error 58 means this clientOrderId is already in use. Look up the existing order. See Mutations, retries and idempotency.

POST /api/v1/wholeblock/cancel-all-orders

Requires bearer authentication and an application/json body.

Supported cancellation scopes: supply a nonblank instrumentId to cancel orders for one instrument. Omit instrumentId, send null, or send a blank string to cancel orders across all instruments of this market family for the specified account. Both modes are intentional API features.

To cancel every instrument, send your accountId only. The example below selects one instrument.

Example request:

{
  "accountId": 128,
  "instrumentId": "ETH-WB-9884031"
}

Send a reviewed request.json containing the JSON body above. Set ETHGAS_BASE_URL and ETHGAS_ACCESS_TOKEN for your environment.

curl --request POST "$ETHGAS_BASE_URL/api/v1/wholeblock/cancel-all-orders" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json
import json
import os
import requests

with open("request.json", encoding="utf-8") as request_file:
    payload = json.load(request_file)
response = requests.post(
    os.environ["ETHGAS_BASE_URL"].rstrip("/") + "/api/v1/wholeblock/cancel-all-orders",
    headers={"Authorization": "Bearer " + os.environ["ETHGAS_ACCESS_TOKEN"]},
    json=payload,
    timeout=30,
)
# Check HTTP status and content type before interpreting the JSON envelope.
print(response.status_code, response.text)

Request Body

Parameter Required Type Description
accountId YES integer Account whose orders are canceled.
instrumentId NO string Omitted, null or blank cancels across ALL instruments in this market family.

Response Body

Normal completion returns data.code=0.

{"success":true,"data":{"code":0}}

A rejected request has success false, with errorCode and errorMsgKey. Missing account is 91. Missing instrument is 92. An invalid ID choice is 93 or 94. An invalid client order ID is 95. A batch above the limit is 96.

POST /api/v1/wholeblock/cancel-batch-orders

Requires bearer authentication and an application/json body.

Supply exactly one ID family. Sending both or neither is rejected. Each batch accepts at most 100 IDs.

Example request:

{
  "accountId": 128,
  "instrumentId": "ETH-WB-9884031",
  "clientOrderIds": [
    "exampleOrder0001",
    "exampleOrder0002"
  ]
}

Send a reviewed request.json containing the JSON body above. Set ETHGAS_BASE_URL and ETHGAS_ACCESS_TOKEN for your environment.

curl --request POST "$ETHGAS_BASE_URL/api/v1/wholeblock/cancel-batch-orders" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json
import json
import os
import requests

with open("request.json", encoding="utf-8") as request_file:
    payload = json.load(request_file)
response = requests.post(
    os.environ["ETHGAS_BASE_URL"].rstrip("/") + "/api/v1/wholeblock/cancel-batch-orders",
    headers={"Authorization": "Bearer " + os.environ["ETHGAS_ACCESS_TOKEN"]},
    json=payload,
    timeout=30,
)
# Check HTTP status and content type before interpreting the JSON envelope.
print(response.status_code, response.text)

Request Body

Parameter Required Type Description
accountId YES integer Account whose orders are canceled.
instrumentId YES string Nonblank instrument ID.
clientOrderIds ONE FAMILY string[] ASCII alphanumeric ID(s), 1–32 characters each. Do not send null elements.
orderIds ONE FAMILY integer Alternative server-assigned numeric ID(s). Do not use hex strings.

Response Body

The outer success indicates the request was handled. Inspect every data.orders[].code: 0 succeeds, 90 means no matching order. Individual failures can appear under success: true.

{
  "success": true,
  "data": {
    "orders": [
      {
        "code": 0,
        "errorMsg": "success",
        "accountId": 128,
        "orderId": 204415806,
        "clientOrderId": "exampleOrder0001"
      }
    ]
  }
}
Field Type Description
orders object[] Per-order results.
orders[].code integer Operation result; see cancellation codes 90–96.
orders[].errorMsg string Message key (not outer errorMsgKey).
orders[].accountId integer Account ID.
orders[].orderId integer (int64) Present when the order was found.
orders[].clientOrderId string Can be omitted when unavailable.

A rejected request has success false, with errorCode and errorMsgKey. Missing account is 91. Missing instrument is 92. An invalid ID choice is 93 or 94. An invalid client order ID is 95. A batch above the limit is 96.

POST /api/v1/wholeblock/cancel-order

Requires bearer authentication and an application/json body.

Supply exactly one ID family. Sending both or neither is rejected.

Example request:

{
  "accountId": 128,
  "instrumentId": "ETH-WB-9884031",
  "clientOrderId": "exampleOrder0001"
}

Send a reviewed request.json containing the JSON body above. Set ETHGAS_BASE_URL and ETHGAS_ACCESS_TOKEN for your environment.

curl --request POST "$ETHGAS_BASE_URL/api/v1/wholeblock/cancel-order" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json
import json
import os
import requests

with open("request.json", encoding="utf-8") as request_file:
    payload = json.load(request_file)
response = requests.post(
    os.environ["ETHGAS_BASE_URL"].rstrip("/") + "/api/v1/wholeblock/cancel-order",
    headers={"Authorization": "Bearer " + os.environ["ETHGAS_ACCESS_TOKEN"]},
    json=payload,
    timeout=30,
)
# Check HTTP status and content type before interpreting the JSON envelope.
print(response.status_code, response.text)

Request Body

Parameter Required Type Description
accountId YES integer Account whose orders are canceled.
instrumentId YES string Nonblank instrument ID.
clientOrderId ONE FAMILY string ASCII alphanumeric ID(s), 1–32 characters each. Do not send null elements.
orderId ONE FAMILY integer (int64) Alternative server-assigned numeric ID(s). Do not use hex strings.

Response Body

The outer success indicates the request was handled. Inspect every data.orders[].code: 0 succeeds, 90 means no matching order. Individual failures can appear under success: true.

{
  "success": true,
  "data": {
    "orders": [
      {
        "code": 0,
        "errorMsg": "success",
        "accountId": 128,
        "orderId": 204415806,
        "clientOrderId": "exampleOrder0001"
      }
    ]
  }
}
Field Type Description
orders object[] Per-order results.
orders[].code integer Operation result; see cancellation codes 90–96.
orders[].errorMsg string Message key (not outer errorMsgKey).
orders[].accountId integer Account ID.
orders[].orderId integer (int64) Present when the order was found.
orders[].clientOrderId string Can be omitted when unavailable.

A rejected request has success false, with errorCode and errorMsgKey. Missing account is 91. Missing instrument is 92. An invalid ID choice is 93 or 94. An invalid client order ID is 95. A batch above the limit is 96.

GET /api/v1/user/wholeblock/all-orders

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/wholeblock/all-orders?onBook=false&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/wholeblock/all-orders"

params = {
  "onBook": False,
  "limit": 10
}

headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
  "success": true,
  "data": {
    "orders": [
      {
        "orderId": 204421028,
        "marketId": 2000009884031,
        "instrumentId": "ETH-WB-9884031",
        "accountId": 128,
        "side": false,
        "orderType": 1,
        "quantity": "1",
        "fulfilled": "1",
        "price": "0.01",
        "averageTradePrice": "0.01",
        "fees": "0.0001",
        "status": 10,
        "clientOrderId": "y0xja3Xi",
        "passive": false,
        "createDate": 1697449610000,
        "source": 1,
        "updateDate": 1697449609000
      }
    ],
    "hasNextPage": false
  }
}

Get all user whole block orders for a given user account ID.

Request

Parameter Required Type Description
accountId NO integer Default: session preconf account; explicit accounts require read access.
onBook NO boolean Open orders only; default false.
startId NO integer (int64) Exclusive order cursor. Omitted for the first page.
asc NO boolean Default true; see pagination limitations.
limit NO integer Default 10; positive values; capped at 1000.

hasNextPage is true when more orders match. Send nextCursor as startId with the same filters and direction. The last page has hasNextPage false and no nextCursor. See Pagination and filters.

Response Body

Name Type Description
hasNextPage boolean True when the query found another matching row beyond this page.
nextCursor integer (int64) Last returned order ID; present only when hasNextPage is true.
orders object[] List of order object
└ orderId integer Unique order ID, assigned by ETHGas
└ marketId integer Market ID for this order
└ instrumentId string Whole block market instrument ID
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ side boolean buy order (true) or sell order (false)
└ orderType integer Market (1), limit (2), or FOK (3)
└ quantity string Order quantity (1 for whole block orders)
└ fulfilled string Quantity that has already been executed
└ price string Price of the order
└ averageTradePrice string Average price of executed trades
└ fees string Fees charged for this order
└ status integer Order status - see the Order Status Codes section for more information
└ errorCode integer Error code if order failed (omitted if absent)
└ clientOrderId string Client order ID: 1–32 ASCII letters/digits, matching ^[a-zA-Z0-9]{1,32}$
└ passive boolean Whether the order is a maker order only
└ createDate integer Datetime (Unix epoch milliseconds) when the order was created
└ source integer Where the order is originated
└ updateDate integer Datetime (Unix epoch milliseconds) when the order was last updated

GET /api/v1/user/wholeblock/orders

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/wholeblock/orders?accountId=128&instrumentId=ETH-WB-9884031"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/wholeblock/orders"

params = {
  "instrumentId": "ETH-WB-9884031"
}

headers = {
   'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
  "success": true,
  "data": {
    "orders": [
      {
        "orderId": 204421028,
        "marketId": 2000009884031,
        "instrumentId": "ETH-WB-9884031",
        "accountId": 128,
        "side": false,
        "orderType": 1,
        "quantity": "1",
        "fulfilled": "1",
        "price": "0.01",
        "averageTradePrice": "0.01",
        "fees": "0.0001",
        "status": 10,
        "clientOrderId": "y0xja3Xi",
        "passive": false,
        "createDate": 1697449610000,
        "source": 1,
        "updateDate": 1697449609000
      }
    ]
  }
}

Get user whole block orders for a given account ID (and instrument ID).

Request

Parameter Required Type Description
accountId NO integer Default: session preconf account; explicit accounts require read access.
instrumentId NO string Optional instrument filter.
onBook NO boolean Open orders only; default false.
done NO boolean Status 10 only; default false; mutually exclusive with onBook=true.
startId NO integer (int64) Exclusive order cursor. Omit for the first page in either direction.
asc NO boolean Default true; see pagination limitations.
limit NO integer Default 10; positive values; capped at 1000.

Response Body

Name Type Description
orders object[] List of order object
└ orderId integer Unique order ID, assigned by ETHGas
└ marketId integer Market ID for this order
└ instrumentId string Whole block market instrument ID

Use endpoint [GET /api/v1/wholeblock/markets] to get a list of all available wholeblock markets' instrument IDs
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ side boolean buy order (true) or sell order (false)
└ orderType integer Market (1), limit (2), or FOK (3)

If an order is sent with both a price specified and an orderType of 1, then a maximum slippage order is created
└ quantity string Order quantity (1 for whole block orders)
└ fulfilled string Quantity that has already been executed
└ price string Price of the order
└ averageTradePrice string Average price of executed trades
└ fees string Fees charged for this order
└ status integer Order status - see the Order Status Codes section for more information
└ errorCode integer Error code if order failed (omitted if absent)
└ clientOrderId string Client order ID: 1–32 ASCII letters/digits, matching ^[a-zA-Z0-9]{1,32}$
└ passive boolean (Post-only) Whether the order is a maker order only (i.e. can only be lifted, but cannot lift/take any orders from the orderbook itself - in other words, can only add liquidity)

If set to false, there are no such restrictions and the order can immediately lift (i.e. take) existing orders in the orderbook if it is crossing the bid/sell price spread
└ createDate integer Datetime (Unix epoch milliseconds) when the order was created
└ source integer Where the order is originated

1: User interface
5: TWAP
└ updateDate integer Datetime (Unix epoch milliseconds) when the order was last updated
└ trades object[] List of executed trades for this order
 └ side boolean Order side - buy (true) or sell (false)
 └ rate string Price executed
 └ quantity string Quantity executed
 └ date integer Datetime (Unix epoch milliseconds) executed

GET /api/v1/user/wholeblock/positions

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/wholeblock/positions?instrumentId=ETH-WB-9884031&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/wholeblock/positions"

params = {
  "instrumentId": "ETH-WB-9884031",
  "limit": 10
}

headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
  "success": true,
  "data": {
    "positions": [
      {
        "positionId": 204421028,
        "instrumentId": "ETH-WB-9884031",
        "accountId": 128,
        "side": false,
        "orderType": 1,
        "quantity": "1",
        "fulfilled": "1",
        "status": 10,
        "clientOrderId": "y0xja3Xi",
        "passive": false,
        "orderDate": 1697449610000,
        "source": 1,
        "updateDate": 1697449609000,
        "averageTradePrice": "0.047",
        "trades": [
          {
            "side": false,
            "price": "0.047",
            "quantity": "1",
            "date": 1697449609000
          }
        ]
      }
    ]
  }
}

Get user wholeblock positions for a given account ID (and instrument ID).

Request

Parameter Required Type Description
accountId NO integer Default: session preconf account; explicit accounts require read access.
instrumentId NO string Optional instrument filter.
startId NO integer (int64) Slot cursor; omitted for the first page.
enable NO boolean Active positions only; default true.
asc NO boolean Default false (descending).
limit NO integer Default 10; positive values; capped at 1000.

Response Body

Name Type Description
positions object[] List of position object
└ positionId integer Unique position ID, assigned by ETHGas
└ instrumentId string Whole block market instrument ID

Use endpoint [GET /api/v1/wholeblock/markets] to get a list of all available wholeblock markets' instrument IDs
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ quantity string Order quantity
└ status integer Order status - see the Order Status Codes section for more information
└ passive boolean (Post-only) Whether the order is a maker order only (i.e. can only be lifted, but cannot lift/take any orders from the orderbook itself - in other words, can only add liquidity)

If set to false, there are no such restrictions and the order can immediately lift (i.e. take) existing orders in the orderbook if it is crossing the bid/sell price spread
└ createDate integer Datetime (Unix epoch milliseconds) when the position was updated
└ source integer Where the order is originated

1: User interface
5: TWAP
└ updateDate integer Datetime (Unix epoch milliseconds) something last occurred to the order
└ trades object[] List of executed trades for this order
 └ side boolean Order side - buy (true) or sell (false)
 └ rate string Price executed
 └ quantity string Quantity executed
 └ date integer Datetime (Unix epoch milliseconds) executed

GET /api/v1/user/wholeblock/txs

Get the user transactions for wholeblock market

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/wholeblock/txs?instrumentId=ETH-WB-63999&limit=100"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/wholeblock/txs"

params = {
  "instrumentId": "ETH-WB-63999",
  "limit": 10
}

headers = {
  'Authorization': 'Bearer {{access_token}}'
}


response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "txs": [
            {   "buyerAccountId": 14,
                "sellerAccountId": 2049,
                "instrumentId": "ETH-WB-63999",
                "trxId": 11675386,
                "side": false,
                "price": "0.00000002",
                "quantity": "1",
                "preconfQuantity": "320000000",
                "date": 1730269305359
            },
            {   "buyerAccountId": 2015,
                "sellerAccountId": 14,
                "instrumentId": "ETH-WB-63999",
                "trxId": 11675385,
                "side": true,
                "price": "0.00000002",
                "quantity": "1",
                "preconfQuantity": "350000000",
                "date": 1730269208878
            }
        ]
    }
}

Request

Parameter Required Type Description
accountId YES integer Readable account ID.
instrumentId NO string Optional instrument filter.
orderId NO integer (int64) If supplied, selects the order-specific branch; instrumentId, startId and limit do not control that branch.
startId NO integer (int64) Transaction cursor for the general list branch.
limit NO integer Default 20; positive values; capped at 1000 for the general list branch.

Response Body

Name Type Description
txs object[] List of trades
└ instrumentId string Whole block market instrument ID

Use endpoint GET /api/v1/p/wholeblock/markets to get a list of all available whole block markets' instrument IDs
└ trxId integer Transaction Id
└ buyerAccountId integer Buyer Account Id
└ sellerAccountId integer Seller Account Id
└ side integer Order Side. Buy = 1, Sell = 0
└ price string Latest traded market price for this market
└ quantity integer Quantity always = 1
└ preconfQuantity integer Preconf quantity sold with the whole block
└ date integer Datetime (Unix epoch milliseconds) when the market orderbook was last updated

Inclusion Preconf Trading

POST /api/v1/inclusion-preconf/cancel-all-orders

Requires bearer authentication and an application/json body.

Supported cancellation scopes: supply a nonblank instrumentId to cancel orders for one instrument. Omit instrumentId, send null, or send a blank string to cancel orders across all instruments of this market family for the specified account. Both modes are intentional API features.

To cancel every instrument, send your accountId only. The example below selects one instrument.

Example request:

{
  "accountId": 128,
  "instrumentId": "ETH-PC-9884031"
}

Send a reviewed request.json containing the JSON body above. Set ETHGAS_BASE_URL and ETHGAS_ACCESS_TOKEN for your environment.

curl --request POST "$ETHGAS_BASE_URL/api/v1/inclusion-preconf/cancel-all-orders" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json
import json
import os
import requests

with open("request.json", encoding="utf-8") as request_file:
    payload = json.load(request_file)
response = requests.post(
    os.environ["ETHGAS_BASE_URL"].rstrip("/") + "/api/v1/inclusion-preconf/cancel-all-orders",
    headers={"Authorization": "Bearer " + os.environ["ETHGAS_ACCESS_TOKEN"]},
    json=payload,
    timeout=30,
)
# Check HTTP status and content type before interpreting the JSON envelope.
print(response.status_code, response.text)

Request Body

Parameter Required Type Description
accountId YES integer Account whose orders are canceled.
instrumentId NO string Omitted, null or blank cancels across ALL instruments in this market family.

Response Body

Normal completion returns data.code=0.

{"success":true,"data":{"code":0}}

A rejected request has success false, with errorCode and errorMsgKey. Missing account is 91. Missing instrument is 92. An invalid ID choice is 93 or 94. An invalid client order ID is 95. A batch above the limit is 96.

POST /api/v1/inclusion-preconf/cancel-batch-orders

Requires bearer authentication and an application/json body.

Supply exactly one ID family. Sending both or neither is rejected. Each batch accepts at most 100 IDs.

Example request:

{
  "accountId": 128,
  "instrumentId": "ETH-PC-9884031",
  "clientOrderIds": [
    "exampleOrder0001",
    "exampleOrder0002"
  ]
}

Send a reviewed request.json containing the JSON body above. Set ETHGAS_BASE_URL and ETHGAS_ACCESS_TOKEN for your environment.

curl --request POST "$ETHGAS_BASE_URL/api/v1/inclusion-preconf/cancel-batch-orders" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json
import json
import os
import requests

with open("request.json", encoding="utf-8") as request_file:
    payload = json.load(request_file)
response = requests.post(
    os.environ["ETHGAS_BASE_URL"].rstrip("/") + "/api/v1/inclusion-preconf/cancel-batch-orders",
    headers={"Authorization": "Bearer " + os.environ["ETHGAS_ACCESS_TOKEN"]},
    json=payload,
    timeout=30,
)
# Check HTTP status and content type before interpreting the JSON envelope.
print(response.status_code, response.text)

Request Body

Parameter Required Type Description
accountId YES integer Account whose orders are canceled.
instrumentId YES string Nonblank instrument ID.
clientOrderIds ONE FAMILY string[] ASCII alphanumeric ID(s), 1–32 characters each. Do not send null elements.
orderIds ONE FAMILY integer Alternative server-assigned numeric ID(s). Do not use hex strings.

Response Body

The outer success indicates the request was handled. Inspect every data.orders[].code: 0 succeeds, 90 means no matching order. Individual failures can appear under success: true.

{
  "success": true,
  "data": {
    "orders": [
      {
        "code": 0,
        "errorMsg": "success",
        "accountId": 128,
        "orderId": 204415806,
        "clientOrderId": "exampleOrder0001"
      }
    ]
  }
}
Field Type Description
orders object[] Per-order results.
orders[].code integer Operation result; see cancellation codes 90–96.
orders[].errorMsg string Message key (not outer errorMsgKey).
orders[].accountId integer Account ID.
orders[].orderId integer (int64) Present when the order was found.
orders[].clientOrderId string Can be omitted when unavailable.

A rejected request has success false, with errorCode and errorMsgKey. Missing account is 91. Missing instrument is 92. An invalid ID choice is 93 or 94. An invalid client order ID is 95. A batch above the limit is 96.

POST /api/v1/inclusion-preconf/cancel-order

Requires bearer authentication and an application/json body.

Supply exactly one ID family. Sending both or neither is rejected.

Example request:

{
  "accountId": 128,
  "instrumentId": "ETH-PC-9884031",
  "clientOrderId": "exampleOrder0001"
}

Send a reviewed request.json containing the JSON body above. Set ETHGAS_BASE_URL and ETHGAS_ACCESS_TOKEN for your environment.

curl --request POST "$ETHGAS_BASE_URL/api/v1/inclusion-preconf/cancel-order" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json
import json
import os
import requests

with open("request.json", encoding="utf-8") as request_file:
    payload = json.load(request_file)
response = requests.post(
    os.environ["ETHGAS_BASE_URL"].rstrip("/") + "/api/v1/inclusion-preconf/cancel-order",
    headers={"Authorization": "Bearer " + os.environ["ETHGAS_ACCESS_TOKEN"]},
    json=payload,
    timeout=30,
)
# Check HTTP status and content type before interpreting the JSON envelope.
print(response.status_code, response.text)

Request Body

Parameter Required Type Description
accountId YES integer Account whose orders are canceled.
instrumentId YES string Nonblank instrument ID.
clientOrderId ONE FAMILY string ASCII alphanumeric ID(s), 1–32 characters each. Do not send null elements.
orderId ONE FAMILY integer (int64) Alternative server-assigned numeric ID(s). Do not use hex strings.

Response Body

The outer success indicates the request was handled. Inspect every data.orders[].code: 0 succeeds, 90 means no matching order. Individual failures can appear under success: true.

{
  "success": true,
  "data": {
    "orders": [
      {
        "code": 0,
        "errorMsg": "success",
        "accountId": 128,
        "orderId": 204415806,
        "clientOrderId": "exampleOrder0001"
      }
    ]
  }
}
Field Type Description
orders object[] Per-order results.
orders[].code integer Operation result; see cancellation codes 90–96.
orders[].errorMsg string Message key (not outer errorMsgKey).
orders[].accountId integer Account ID.
orders[].orderId integer (int64) Present when the order was found.
orders[].clientOrderId string Can be omitted when unavailable.

A rejected request has success false, with errorCode and errorMsgKey. Missing account is 91. Missing instrument is 92. An invalid ID choice is 93 or 94. An invalid client order ID is 95. A batch above the limit is 96.

POST /api/v1/inclusion-preconf/order

Requires bearer authentication and an application/json body.

Example request:

{
  "accountId": 128,
  "instrumentId": "ETH-PC-9884031",
  "side": true,
  "orderType": 2,
  "clientOrderId": "exampleOrder0001",
  "passive": false,
  "price": "0.00000000569",
  "quantity": "21000"
}

Send a reviewed request.json containing the JSON body above. Set ETHGAS_BASE_URL and ETHGAS_ACCESS_TOKEN for your environment.

curl --request POST "$ETHGAS_BASE_URL/api/v1/inclusion-preconf/order" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json
import json
import os
import requests

with open("request.json", encoding="utf-8") as request_file:
    payload = json.load(request_file)
response = requests.post(
    os.environ["ETHGAS_BASE_URL"].rstrip("/") + "/api/v1/inclusion-preconf/order",
    headers={"Authorization": "Bearer " + os.environ["ETHGAS_ACCESS_TOKEN"]},
    json=payload,
    timeout=30,
)
# Check HTTP status and content type before interpreting the JSON envelope.
print(response.status_code, response.text)

Request Body

Parameter Required Type Description
accountId YES integer Trading/preconf account ID. Missing/zero is rejected.
instrumentId CONDITIONAL string Market instrument. Canonical selector; discover an active market first.
marketId CONDITIONAL integer (int64) Alternative market identifier. Supply one unambiguous market selector; do not send conflicting identifiers.
side YES boolean Buy true, sell false.
orderType YES integer 1 market, 2 limit, 3 fill-or-kill (FOK).
clientOrderId YES string 1–32 ASCII letters/digits; ^[a-zA-Z0-9]{1,32}$. Retain for reconciliation.
passive NO boolean Default false; post-only when true. FOK with passive=true is rejected.
price CONDITIONAL decimal string ETH per gas. Required and positive for limit/FOK; obey market min/max/step. For market orders, omit for a regular market order; a supplied price is a slippage limit.
quantity YES decimal string Positive gas quantity; obey market min/max/step.

Send price and quantity as decimal strings, within the market minimum, maximum, and step. Omit response fields such as fees, fulfilled, status, and orderId.

Response Body

This response confirms that the order was accepted. It includes orderDate. Order lists use createDate and updateDate, and that is where you read fees and averageTradePrice. If the request sends only instrumentId, marketId can be 0. Read the market from the market list.

Field in data.order Type Description
orderId integer (int64) Assigned order ID.
accountId / instrumentId / side / orderType / passive / clientOrderId request types Submitted order parameters.
marketId integer (int64) May remain 0 for instrument-only requests.
quantity / fulfilled / price decimal string Quantity, executed quantity and submitted price; absent nullable fields may be omitted.
status integer See Order Status Codes; acknowledgement is not proof of full execution.
orderDate integer Order timestamp in epoch milliseconds.
source integer 1 for orders submitted through this REST path.
preconfQuantity integer Integer gas quantity.

Example response:

{
  "success": true,
  "data": {
    "order": {
      "accountId": 128,
      "instrumentId": "ETH-PC-9884031",
      "side": true,
      "orderType": 2,
      "clientOrderId": "exampleOrder0001",
      "passive": false,
      "price": "0.00000000569",
      "quantity": "21000",
      "orderId": 204415806,
      "marketId": 0,
      "fulfilled": "0",
      "status": 1,
      "source": 1,
      "orderDate": 1790812800000
    }
  }
}

Error 58 means this clientOrderId is already in use. Look up the existing order. See Mutations, retries and idempotency.

GET /api/v1/user/inclusion-preconf/orders

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/inclusion-preconf/orders?accountId=128&instrumentId=ETH-PC-9884031"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/inclusion-preconf/orders"

params = {
  "accountId": 128,
  "instrumentId": "ETH-PC-9884031"
}

headers = {
   'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
  "success": true,
  "data": {
    "orders": [
      {
        "orderId": 204421028,
        "marketId": 1000009884031,
        "accountId": 128,
        "instrumentId": "ETH-PC-9884031",
        "side": false,
        "orderType": 1,
        "quantity": "994.66",
        "fulfilled": "994.66",
        "price": "0.00000000535",
        "fees": "0",
        "status": 10,
        "clientOrderId": "y0xja3Xi",
        "passive": false,
        "createDate": 1697449610000,
        "source": 1,
        "updateDate": 1697449609000
      },
      {
        "orderId": 204421029,
        "marketId": 1000009884031,
        "accountId": 126,
        "instrumentId": "ETH-PC-9884031",
        "side": false,
        "orderType": 1,
        "quantity": "20000",
        "fulfilled": "20000",
        "price": "0.00000000535",
        "fees": "0.0000000000013",
        "status": 10,
        "clientOrderId": "abdc2werf",
        "passive": false,
        "createDate": 1697449630000,
        "source": 1,
        "updateDate": 1697449659000
      }
    ]
  }
}

Get user preconfs orders for a given account ID (and instrument ID).

Request

Parameter Required Type Description
accountId NO integer Default: session preconf account; explicit accounts require read access.
instrumentId NO string Optional instrument filter.
onBook NO boolean Open orders only; default false.
done NO boolean Status 10 only; default false; mutually exclusive with onBook=true.
startId NO integer (int64) Exclusive order cursor. Omitted for the first page.
asc NO boolean Default false; see pagination limitations.
limit NO integer Default 10; positive values; capped at 1000.

Response Body

Name Type Description
orders object[] List of order object
└ orderId integer Unique order ID, assigned by ETHGas
└ marketId integer ETHGas marketId
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ instrumentId string Inclusion Preconf market instrument ID

Use endpoint [GET /api/v1/inclusion-preconf/markets] to get a list of all available inclusion preconf markets' instrument IDs
└ side boolean buy order (true) or sell order (false)
└ orderType integer Market (1), limit (2), or FOK (3)

If an order is sent with both a price specified and an orderType of 1, then a maximum slippage order is created
└ quantity string Order quantity
└ fulfilled string Quantity executed
└ status integer Order status - see the Order Status Codes section for more information
└ clientOrderId string Client order ID: 1–32 ASCII letters/digits, matching ^[a-zA-Z0-9]{1,32}$
└ passive boolean (Post-only) Whether the order is a maker order only (i.e. can only be lifted, but cannot lift/take any orders from the orderbook itself - in other words, can only add liquidity)

If set to false, there are no such restrictions and the order can immediately lift (i.e. take) existing orders in the orderbook if it is crossing the bid/sell price spread
└ createDate integer Datetime (Unix epoch milliseconds) when the order was placed
└ source integer Where the order is originated

1: User interface
5: TWAP
└ updateDate integer Datetime (Unix epoch milliseconds) something last occurred to the order

GET /api/v1/user/inclusion-preconf/all-orders

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/inclusion-preconf/all-orders?limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/inclusion-preconf/all-orders"

params = {
    "limit": 10
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
  "success": true,
  "data": {
    "orders": [
      {
        "orderId": 123456789,
        "clientOrderId": "order123",
        "instrumentId": "ETH-PC-475423",
        "side": true,
        "orderType": 1,
        "quantity": "1000",
        "price": "0.0000000125",
        "status": "ACTIVE"
      }
    ],
    "hasNextPage": false
  }
}

Get all user preconf orders for a given user account ID.

Request

Parameter Required Type Description
accountId NO integer Default: session preconf account; explicit accounts require read access.
onBook NO boolean Open orders only; default false.
startId NO integer (int64) Exclusive order cursor. Omitted for the first page.
asc NO boolean Default true; see pagination limitations.
limit NO integer Default 10; positive values; capped at 1000.

hasNextPage is true when more orders match. Send nextCursor as startId with the same filters and direction. The last page has hasNextPage false and no nextCursor. See Pagination and filters.

Response Body

Name Type Description
orders object[] List of orders
└ orderId long System order ID
└ clientOrderId string Client order ID
└ instrumentId string Instrument ID
└ side boolean Order side (true = buy, false = sell)
└ orderType integer Order type
└ quantity string Order quantity
└ price string Order price
└ status string Order status
hasNextPage boolean True when the query found another matching row beyond this page
nextCursor integer (int64) Last returned order ID; present only when hasNextPage is true

GET /api/v1/user/inclusion-preconf/positions

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/inclusion-preconf/positions?instrumentId=ETH-PC-9884031&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/inclusion-preconf/positions"

params = {
  "instrumentId": "ETH-PC-9884031",
  "limit": 10
}

headers = {
  'Authorization': 'Bearer {{access_token}}'
}


response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
  "success": true,
  "data": {
    "positions": [
      {
        "positionId": 204421028,
        "instrumentId": "ETH-PC-9884031",
        "accountId": 128,
        "side": false,
        "orderType": 1,
        "quantity": "994.66",
        "fulfilled": "994.66",
        "status": 10,
        "clientOrderId": "y0xja3Xi",
        "passive": false,
        "orderDate": 1697449610000,
        "source": 1,
        "updateDate": 1697449609000,
        "averageTradePrice": "0.047",
        "trades": [
          {
            "side": false,
            "price": "0.047",
            "quantity": "994.66",
            "date": 1697449609000
          }
        ]
      },
      {
        "positionId": 204421027,
        "instrumentId": "ETH-PC-9884031",
        "accountId": 128,
        "side": true,
        "orderType": 1,
        "quantity": "922.58",
        "fulfilled": "922.58",
        "status": 10,
        "clientOrderId": "f5onoOtR",
        "passive": false,
        "orderDate": 1697449610000,
        "source": 1,
        "updateDate": 1697449609000,
        "averageTradePrice": "0.0338",
        "trades": [
          {
            "side": true,
            "price": "0.0338",
            "quantity": "922.58",
            "date": 1697449609000
          }
        ]
      }
    ]
  }
}

Get user preconfs positions for a given account ID (and instrument ID).

Request

Parameter Required Type Description
accountId NO integer Default: session preconf account; explicit accounts require read access.
instrumentId NO string Optional instrument filter.
startId NO integer (int64) Slot cursor; omitted for the first page.
enable NO boolean Active positions only; default true.
asc NO boolean Default false (descending).
limit NO integer Default 10; positive values; capped at 1000.

Response Body

Name Type Description
positions object[] List of position object
└ positionId integer Unique position ID, assigned by ETHGas
└ instrumentId string Inclusion Preconf market instrument ID

Use endpoint [GET /api/v1/inclusion-preconf/markets] to get a list of all available inclusion preconf markets' instrument IDs
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ quantity string Order quantity
└ status integer Order status - see the Order Status Codes section for more information
└ passive boolean (Post-only) Whether the order is a maker order only (i.e. can only be lifted, but cannot lift/take any orders from the orderbook itself - in other words, can only add liquidity)

If set to false, there are no such restrictions and the order can immediately lift (i.e. take) existing orders in the orderbook if it is crossing the bid/sell price spread
└ createDate integer Datetime (Unix epoch milliseconds) when the position was updated
└ source integer Where the order is originated

1: User interface
5: TWAP
└ updateDate integer Datetime (Unix epoch milliseconds) something last occurred to the order

GET /api/v1/user/inclusion-preconf/txs

Get the user transactions for inclusion preconfs

Code sample:

curl  -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/inclusion-preconf/txs?instrumentId=ETH-PC-9884031&limit=100"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/inclusion-preconf/txs"

params = {
  "instrumentId": "ETH-PC-9884031",
  "limit": 100
}
headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "txs": [
            {   "buyerAccountId": 14,
                "sellerAccountId": 2049,
                "instrumentId": "ETH-WB-63999",
                "trxId": 11675386,
                "side": false,
                "price": "0.00000002",
                "quantity": "0",
                "date": 1730269305359
            },
            {   "buyerAccountId": 14,
                "sellerAccountId": 2015,
                "instrumentId": "ETH-WB-63999",
                "trxId": 11675385,
                "side": false,
                "price": "0.00000002",
                "quantity": "0",
                "date": 1730269208878
            },
            {
                "buyerAccountId": 20,
                "sellerAccountId": 14,
                "instrumentId": "ETH-WB-63999",
                "trxId": 11675384,
                "side": false,
                "price": "0.00000002",
                "quantity": "0",
                "date": 1730269152774
            },
            {   "buyerAccountId": 2079,
                "sellerAccountId": 14,
                "instrumentId": "ETH-WB-63999",
                "trxId": 11675383,
                "side": false,
                "price": "0.00000002",
                "quantity": "0",
                "date": 1730269084507
            }
        ]
    }
}

Request

Parameter Required Type Description
accountId YES integer Readable account ID.
instrumentId NO string Optional instrument filter.
orderId NO integer (int64) If supplied, selects the order-specific branch; instrumentId, startId and limit do not control that branch.
startId NO integer (int64) Transaction cursor for the general list branch.
limit NO integer Default 20; positive values; capped at 1000 for the general list branch.

Response Body

Name Type Description
txs object[] List of trades
└ instrumentId string Preconf Market instrument ID

Use endpoint [GET /api/v1/p/inclusion-preconf/markets] to get a list of all available inclusion preconf markets' instrument IDs
└ trxId integer Transaction Id
└ buyerAccountId integer Buyer Account Id
└ sellerAccountId integer Seller Account Id
└ side integer Order Side. Buy = 1, Sell = 0
└ price string Latest traded market price for this market
└ quantity integer Quantity always = 1
└ date intger Datetime (Unix epoch milliseconds) when the market orderbook was last updated

POST /api/v1/user/inclusion-preconf/market/update

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/inclusion-preconf/market/update?instrumentId=ETH-PC-475423&reservedQty=1000"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/inclusion-preconf/market/update"

payload = {
    'instrumentId': 'ETH-PC-475423',
    'reservedQty': 1000
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {}
}

Block owner reserve Inclusion Preconfs.

Request

Parameter Required Type Description
instrumentId YES String Instrument ID
reservedQty YES Integer Reserved quantity

Response Body

Name Type Description
success boolean Operation success status

Bundle Submission

POST /api/v1/user/bundle/send

Requires bearer authentication and an application/json body. The account is the session's preconf account. Ordering applies to the whole bundle, not individual transactions.

Send a non-empty txs array to submit a bundle. Omit txs, or send null, to cancel the bundle for that slot, account, and replacementUuid. If no bundle matches, the response is error 193. An empty array submits a bundle and does not cancel one.

To cancel, send slot and replacementUuid with txs omitted or set to null.

Sign each transaction for the selected chain and slot. Use your own nonce and replacement UUID.

curl --request POST "$ETHGAS_BASE_URL/api/v1/user/bundle/send" \
  --header "Authorization: Bearer $ETHGAS_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @bundle.json
import json
import os
import requests

with open("bundle.json", encoding="utf-8") as bundle_file:
    payload = json.load(bundle_file)
response = requests.post(
    os.environ["ETHGAS_BASE_URL"].rstrip("/") + "/api/v1/user/bundle/send",
    headers={"Authorization": "Bearer " + os.environ["ETHGAS_ACCESS_TOKEN"]},
    json=payload,
    timeout=30,
)
print(response.status_code, response.text)

Request Body

Parameter Required Type Description
slot YES integer Target Ethereum slot.
replacementUuid YES string Bundle/replacement identifier; retain for reconciliation.
bundleType NO integer Bundle type. Omit or send 0 for a regular bundle (1).
ordering NO integer Default 0; positive values normalize to 1 (top), negative values to -1 (bottom).
chunkIndex NO integer Default 0, range 0–255. Reconcile chunk/replacement state before retrying.
txs YES FOR SUBMISSION object[] At most 256 transactions per chunk. Omitted/null has cancellation behavior described above.
txs[].tx YES hex string Signed raw transaction; use the target chain and correct nonce.
txs[].canRevert NO boolean Missing/null is false. With true, invalid/undecodable transactions can be skipped during preprocessing, in addition to revert permission.

The server sets createdDate, txs[].nonce, and txs[].trxDataId. Nonce is read from the signed transaction.

Response Body

data echoes the accepted bundle, including server fields. Acceptance is not on-chain inclusion. Use the bundle retrieval endpoints to confirm what was included.

Field in data Type Description
slot integer Target slot.
replacementUuid string Resolved bundle identifier.
bundleType integer Resolved bundle type.
ordering integer Resolved placement.
chunkIndex integer Present when supplied in the request; omission defaults to chunk 0 for submission.
createdDate integer Engine timestamp in epoch milliseconds.
txs object[] Echoed transaction requests when present; may include decoded nonce and storage ID. Omitted for null-list cancellation.

190 means the market has expired. 191 means preconf balance is too low. 192 means the preconf is too large. 193 means the bundle is missing. 194 means the bundle or chunk is invalid. Message keys use the spelling bundleSumission. See Error Codes. If the result is unknown, see Mutations, retries and idempotency.

Slot Bundles

GET /api/v1/slot/bundles

Retrieve bundles for a given slot.

Request

Parameter Required Type Description
slot YES integer Slot ID to retrieve bundles.

Code Sample

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/slot/bundles?slot=123"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/slot/bundles"

params = {
    'slot': 123
}

headers = {
    'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Response Body

Field Type Description
slot integer Slot ID of the retrieved bundles.
emptySpace integer Empty preconf reserved by preconf owner.
isSold boolean The block or preconf has been sold or not.
builders list List of builder address for that slot.
isOfac boolean Whether the slot has OFAC (Office of Foreign Assets Control) restrictions.
feeRecipient string Address of the priority fee receipient (only present when market is expired).
bundles array List of bundles associated with the slot.
└ replacementUuid string Unique identifier for the bundle
└ bidPrice number Average bid price for the bundle
└ bundleType integer Type of the bundle (optional)
└ ordering integer Ordering of the bundle (optional, only present for owner bundles)
└ txs list List of transactions
 └ tx string Signed Transaction (hex encoded)
 └ txHash string Transaction hash (hex encoded)
 └ canRevert boolean revertable: true, non-revertable : false

Example response:

{
  "slot": 123,
  "emptySpace": 0,
  "isSold": true,
  "builders": [
    "0x313233313331330000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "0xa1885d66bef164889a2e35845c3b626545d7b0e513efe335e97c3a45e534013fa3bc38c3b7e6143695aecc4872ac52c4"
  ],
  "isOfac": false,
  "feeRecipient": "0xasdfadflj2lwejf...",
  "bundles": [
    {
      "txs": [
        {
          "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
          "txHash": "0x87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
          "canRevert": false
        },
        {
          "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
          "txHash": "0x87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
          "canRevert": false
        }
      ],
      "replacementUuid": "ab592371-84d6-459e-95e7-5edad485f282",
      "bidPrice": 1.2635975e-08
    },
    {
      "txs": [
        {
          "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
          "canRevert": false,
          "createDate": 1730366973413
        }
      ],
      "replacementUuid": "45727106-d37e-4194-93bc-8650bc135c53fg",
      "bidPrice": 1e-11
    },
    {
      "txs": [
        {
          "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
          "canRevert": false,
          "createDate": 1730366973440
        }
      ],
      "replacementUuid": "19780112-d37e-4194-93bc-8650bc135c53",
      "bidPrice": 1e-11,
      "ordering": 2
    }
  ]
}

GET /api/v1/slot/account/bundles

Retrieve the bundles submitted for a given slot for your inclusion preconf account.

Request

Parameter Required Type Description
slot YES integer Slot ID to retrieve bundles.

Code Sample

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/slot/account/bundles?slot=123"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/slot/account/bundles"

params = {
    'slot': 123
}

headers = {
    'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Response Body

Field Type Description
slot integer Slot ID of the retrieved bundles.
bundles array List of bundles associated with the slot.
└ replacementUuid string Unique identifier for the bundle
└ bidPrice number Bid price for the bundle
└ bundleType integer Type of the bundle (optional)
└ ordering integer Ordering of the bundle (optional, only present for owner bundles)
└ txs list List of transactions
 └ tx string Signed Transaction (hex encoded)
 └ txHash string Transaction hash (hex encoded)
 └ canRevert boolean revertable: true, non-revertable : false

Example response:

{
    "slot": 123,
    "bundles": [
            {
                "txs": [
                    {
                        "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
                        "txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
                        "canRevert": false
                    },
                    {
                        "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
                        "txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
                        "canRevert": false
                    }
                ],
                "replacementUuid": "ab592371-84d6-459e-95e7-5edad485f282",
                "bidPrice": 1.2635975E-8
            },
            {
                "txs": [
                    {
                        "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
                        "txHash": "0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321",
                        "canRevert": false
                    }
                ],
                "replacementUuid": "45727106-d37e-4194-93bc-8650bc135c53fg",
                "bidPrice": 1.0E-11
            },
            {
                "txs": [
                    {
                        "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260",
                        "txHash": "0x9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba",
                        "canRevert": false
                    }
                ],
                "replacementUuid": "19780112-d37e-4194-93bc-8650bc135c53",
                "bidPrice": 1.0E-11,
                "ordering": 1
            }
        ]
}

POST /api/v1/slot/forceEmptyBlockSpace

Preconf owner set unused inclusion preconf gas to be empty for a given slot. It should be set after the inclusion preconf is being bought.

Request

Parameter Required Type Description
slot YES integer Slot ID to update
enable YES boolean true to force empty gas space in the slot

Code Sample

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/slot/forceEmptyBlockSpace?slot=123&enable=true"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/slot/forceEmptyBlockSpace"

params = {
    'slot': 123,
    'enable': True
}

headers = {'Authorization': 'Bearer {{access_token}}'}
response = requests.post(url, params=params, headers=headers)

print(response.text)

Response Body

Field Type Description
success boolean Whether the request succeeded

Example response:

{
    "success": true,
    "data": { "success": true }
}

Builder

POST /api/v1/builder/register

Register builder

Request

Parameter Required Type Description
publicKeys YES string Comma separated list of builder bls public key in hex.
signatures YES string Comma separated list of bls signatures in hex.
ofac NO boolean OFAC flag for the builders (default: false)

Code Sample

POST /api/v1/builder/register?publicKeys=0x12345...,0x234134...&signatures=2asdfjghadg,xghlktdhj&ofac=false HTTP/1.1
Host: prod-mainnet.ethgas.com
Authorization: Bearer {{access_token}}
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/builder/register"

payload = {
    'publicKeys': '0x123456789abcdef...,0x234134...',
    'signatures': '2asdfjghadg,xghlktdhj',
    'ofac': False
}

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "results": [
            {
                "publicKey": "0xa25addc4fc16f72ca667177d7a5533d4287b3574f0127ffc227095e90b0b1fd0dd48c421e04e613d2298fe4dac83a2a5",
                "result": {
                    "result": 0,
                    "description": "Success"
                }
            },
            {
                "publicKey": "0xaea551245bd0512de5222834db5f3bc9cba1a04a2e8f5de0d4fea843c9fee1af31bb9373ba6b9da08a0820f695c6ab6e",
                "result": {
                    "result": 0,
                    "description": "Success"
                }
            }
        ]
    }
}

Response Fields

Field Type Description
results object[] Results of builder public key registrations
└publicKey string Public key in the registration.
└result object Builder Registration Result
└└result integer Builder Registration Result Code
└└description string Builder Registration Result Description

Error Codes

Code Description
INVALID_PUBLIC_KEY Invalid builder public key format
BUILDERS_MAX Maximum 100 builders allowed per request
BUILDER_SIGNATURE_SIZE_NOT_MATCH_PUBLIC_KEY Number of signatures must match number of public keys

Note: Please refer to look up table to check the builder registration result enum

GET /api/v1/builder/signingMessage

Get the required signing message which will be used to sign the BLS signature by using builder's BLS key.

Request

Parameter Required Type Description
N/A N/A N/A No parameters required.

Code Sample

GET /api/v1/builder/signingMessage HTTP/1.1
Host: prod-mainnet.ethgas.com
Authorization: Bearer {{access_token}}
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/builder/signingMessage"

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "message": {
            "eoaAddress": "0xd065335192d920ce2de4a88557f232943a901a9f"
        }
    }
}

Response Fields

Field Type Description
message object Signing message.
└eoaAddress string EOA address of current user

POST /api/v1/builder/deregister

Builder deregistering their public keys from Ethgas

Request

Parameter Required Type Description
publicKeys YES string Comma separated list of builder bls public keys in hex.

Code Sample

POST /api/v1/builder/deregister?publicKeys=0x12342330def...,0x4a93d70def... HTTP/1.1
Host: prod-mainnet.ethgas.com
Authorization: Bearer {{access_token}}
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/builder/deregister"

payload = {
    'publicKeys': '0x12342330def...,0x4a93d70def...'
}

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true
}

Response Fields

Field Type Description
success boolean Whether API call is successful or not

Error Codes

Code Description
INVALID_PUBLIC_KEY Invalid builder public key format
BUILDERS_MAX Maximum 100 builders allowed per request

GET /api/v1/p/builders

Retrieve a list of builders and fallback builder key.

Request

Parameter Required Type Description
ofac NO boolean Filter by OFAC status (default: false)

Code Sample

GET /api/v1/p/builders HTTP/1.1
Host: prod-mainnet.ethgas.com
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/builders"

headers = {
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "builders": {
            "whitelistedBuilders": {
                "btcs": [
                    "0x123456789abcdef...",
                    "0xfb3456789abcdef..."
                ]
            },
            "unnamedBuilders": [
                "0x123456789abcdef...",
                "0xfb3456789abcdef..."
            ],
            "fallbackBuilder": "0xlhadunabcdef..."
        }
    }
}

Response Fields

Field Type Description
builders object List of builder objects.
└ whitelistedBuilders object List of whitelisted builders which can be accessed by builder name.
└ unnamedBuilders List List of public key of unnamed builder in hex.
└ fallbackBuilder string Public key of the ETHGAS fallback builder in hex.

GET /api/v1/p/builder/entity

Retrieve builder entities and the builder keys mapped to each entity.

Request

Parameter Required Type Description
N/A N/A N/A No parameters required.

Code Sample

GET /api/v1/p/builder/entity HTTP/1.1
Host: prod-mainnet.ethgas.com
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/builder/entity"

headers = {
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "builderEntities": [
            {
                "builderEntityId": 1,
                "name": "ETHGAS Builder",
                "builderKeys": [
                    "0x123456789abcdef...",
                    "0xfb3456789abcdef..."
                ]
            }
        ]
    }
}

Response Fields

Field Type Description
builderEntities object[] List of builder entities.
└ builderEntityId integer Builder entity ID.
└ name string Builder entity name.
└ builderKeys string[] Builder BLS public keys mapped to this entity.

GET /api/v1/user/builder

Retrieve a list of builder public keys submitted by a user

Request

Parameter Required Type Description
N/A N/A N/A No parameters required.

Code Sample

GET /api/v1/user/builder HTTP/1.1
Host: prod-mainnet.ethgas.com
Authorization: Bearer {{access_token}}
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/builder"

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "builders": [
            "0xa25addc4fc16f72ca667177d7a5533d4287b3574f0127ffc227095e90b0b1fd0dd48c421e04e613d2298fe4dac83a2a5",
            "0xa6745dd64a0a393497d5a7d4904b613aa386f47eb2e3617cf791f059291f2812683305a4bd562d63ec15990b67795e2a",
            "0xaea551245bd0512de5222834db5f3bc9cba1a04a2e8f5de0d4fea843c9fee1af31bb9373ba6b9da08a0820f695c6ab6e"
        ]
    }
}

Response Fields

Field Type Description
builders string[] List of builder bls keys.

POST /api/v1/user/delegate/builder

Delegate or revoke builder delegation by supplying either builder entity IDs or explicit BLS public keys. Builder account IDs stay internal.

Request

Parameter Required Type Description
builderEntityIds No string A list of comma separated builder entity IDs. Must not be provided with publicKeys.
publicKeys No string A list of comma separated bls builder public keys in hex. Must not be provided with builderEntityIds.
enable Yes boolean Delegate or revoke builder delegation.

Code Sample

POST /api/v1/user/delegate/builder?builderEntityIds=1,2&enable=true HTTP/1.1
Host: prod-mainnet.ethgas.com
Authorization: Bearer {{access_token}}
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/delegate/builder"

payload = {
    'builderEntityIds': '1,2',
    'enable': True
}

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true
}

Response Fields

Field Type Description
success bool Indicates request status.

Error Codes

Code Description
BUILDER_DELEGATION_TARGET_REQUIRED Either builderEntityIds or publicKeys must be provided
BUILDER_DELEGATION_TARGET_CONFLICT builderEntityIds and publicKeys cannot be provided together
BUILDER_DELEGATION_ENTITY_ID_INVALID builderEntityIds contains an invalid builder entity ID

Note: User needs to delegate a new builder entity 2 seconds before the market close in order to be effective in that epoch. If a market owner has no explicit builder entity or key delegation, the slot uses all builder accounts mapped to a builder entity.

POST /api/v1/builder/update/ofac

Update OFAC flag for existing builder

Request

Parameter Required Type Description
publicKeys NO string Comma separated list of builder bls public keys in hex. If not provided, updates all builders for the user
ofac YES boolean OFAC flag for the builders (default: false)

Code Sample

POST /api/v1/builder/update/ofac?publicKeys=0x12345...,0x2df345...&ofac=true HTTP/1.1
Host: prod-mainnet.ethgas.com
Authorization: Bearer {{access_token}}
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/builder/update/ofac"

payload = {
    'publicKeys': '0x123456789abcdef...,0x2df345...',
    'ofac': True
}

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true
}

Response Fields

Field Type Description
success boolean Whether API call is successful or not

GET /api/v1/user/delegate/builder

Get delegated builder keys and delegated builder entities for the current user. The response expands entity-based delegation to current builder keys and includes explicitly delegated public keys.

Request

Parameter Required Type Description
N/A N/A N/A No parameters required.

Code Sample

GET /api/v1/user/delegate/builder HTTP/1.1
Host: prod-mainnet.ethgas.com
Authorization: Bearer {{access_token}}
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/delegate/builder"

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "delegatedBuilders": [
            "0x123456789abcdef...",
            "0xfb3456789abcdef..."
        ],
        "delegatedBuilderEntities": [
            {
                "builderEntityId": 1,
                "builderName": "ETHGAS Builder",
                "delegatedBuilders": [
                    "0xa25addc4fc16f72ca667177d7a5533d4287b3574f0127ffc227095e90b0b1fd0dd48c421e04e613d2298fe4dac83a2a5"
                ]
            }
        ]
    }
}

Response Fields

Field Type Description
delegatedBuilders string[] Builder keys directly delegated through builder key delegation.
delegatedBuilderEntities object[] Builder entities delegated by the current user.
└ builderEntityId integer Builder entity ID.
└ builderName string Builder entity name.
└ delegatedBuilders string[] Builder keys resolved from the delegated builder entity.

GET /api/v1/p/builder/{slot}

Retrieve a list of builders by slot ID.

Request

Parameter Required Type Description
slot YES integer Slot ID to retrieve the builder.

Code Sample

GET /api/v1/p/builder/123 HTTP/1.1
Host: prod-mainnet.ethgas.com
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/builder/123"

headers = {
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success" : true,
    "data": {
        "slot": 123,
        "builders": [
            "0x123456789abcdef...",
            "0x156256789ad4fef..."
        ],
        "fallbackBuilder": "0xdsfa56789abcdef...",
        "ofac": false
    }
}

Response Fields

Field Type Description
slot integer Slot number of the block.
builders string[] List of available builder keys for the queried slot.
fallbackBuilder string Public key of the fallback builder in hexadecimal format
ofac boolean OFAC status for the slot

GET /api/v1/builder/delegation

To retrieve a list of user address of those who have delegated to current users' builder keys.

Request

Parameter Required Type Description
N/A N/A N/A No parameters required.

Code Sample

GET /api/v1/builder/delegation HTTP/1.1
Host: prod-mainnet.ethgas.com
Authorization: Bearer {{access_token}}
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/builder/delegation"

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "builderDelegations": {
            "0xefefdffaddfeefef000...": ["0xabadba...", "0x2asdfadv..."],
            "0xdfg2345dfg0efefdffa...": ["0x58de13...", "0x2ab05ed1..."]
    }
  }
}

Response Fields

Field Type Description
builderDelegation object Mapping of builder delegations from corresponding builder key registered by the user
└ string Corresponding builder key registered by the user
└└ string[] EOA address who delegated to the builder key

POST /api/v1/builder/bundle/reject/{slot}

Reject bundles for a specific slot

Request

Parameter Required Type Description
slot YES integer Slot ID to reject bundles for

Request Body: json { "rejections": [ { "uuid": "bundle-uuid-1", "rejectCode": 1, "txHashList": ["0x123...", "0x456..."], "reason": "Bundle rejection reason" } ] }

Code Sample

POST /api/v1/builder/bundle/reject/123 HTTP/1.1
Host: prod-mainnet.ethgas.com
Authorization: Bearer {{access_token}}
Content-Type: application/json

{
    "rejections": [
        {
            "uuid": "bundle-uuid-1",
            "rejectCode": 1,
            "txHashList": ["0x123...", "0x456..."],
            "reason": "Bundle rejection reason"
        }
    ]
}
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/builder/bundle/reject/123"

payload = {
    "rejections": [
        {
            "uuid": "bundle-uuid-1",
            "rejectCode": 1,
            "txHashList": ["0x123...", "0x456..."],
            "reason": "Bundle rejection reason"
        }
    ]
}

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, json=payload)

print(response.text)

Example response:

{
    "success": true
}

Response Fields

Field Type Description
success boolean Whether API call is successful or not

Error Codes

Code Description
INVALID_SLOT Invalid slot ID (must be >= 0)
BUNDLE_REJECTION_EMPTY Rejections list cannot be empty

GET /api/v1/p/builder/bundle/reject/{slot}/{builderAccountId}

Get bundle rejection information for a specific slot and account

Request

Parameter Required Type Description
slot YES integer Slot ID to retrieve rejections
builderAccountId YES integer Builder account ID

Code Sample

GET /api/v1/p/builder/bundle/reject/123/456 HTTP/1.1
Host: prod-mainnet.ethgas.com
Content-Type: application/json
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/builder/bundle/reject/123/456"

headers = {
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "rejections": [
            {
                "uuid": "bundle-uuid-1",
                "rejectCode": 1,
                "txHashList": ["0x123...", "0x456..."],
                "reason": "Bundle rejection reason"
            }
        ]
    }
}

Response Fields

Field Type Description
rejections object[] List of bundle rejections
└ uuid string Bundle UUID
└ rejectCode integer Rejection code
└ txHashList string[] List of transaction hashes
└ reason string Rejection reason

Error Codes

Code Description
INVALID_SLOT Invalid slot ID (must be > 0)
INVALID_ACCOUNT_ID Invalid account ID (must be > 0)

Validator

GET /api/v1/user/validators

Code sample:

curl  -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/validators"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/validators"

headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "validators": [
            {
                "publicKey": "0x800946ad4fb5f4a0d1f46914cbcdc8f072b462ba8fb2495038897b5f5eac38730d87d0ad00b7bc88e745f4d6d7f1f630",
                "ofac": true,
                "validatorPayoutAddress": "0x123463a4b065722e99115d6c222f267d9cabb524"
            },
            {
                "publicKey": "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b",
                "ofac": false
            }
        ]
    }
}

Get list of user validators.

Request

No parameters for this endpoint.

Response Body

Name Type Description
validators array of object List of validator objects
└ publicKey string Validator public key in hexadecimal format (48 bytes)
└ ofac boolean OFAC compliance status for this validator
└ validatorPayoutAddress string Per-validator payout address in hexadecimal format, or null when not set

GET /api/v1/p/pools

Code sample:

curl -X GET "$ETHGAS_BASE_URL/api/v1/p/pools"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/pools"
response = requests.get(url)
print(response.text)

Example response:

{
    "success": true,
    "data": {
        "poolEntities": [
            { "poolEntityId": 1, "name": "Example Pool" }
        ]
    }
}

Get list of pool entities.

Request

No parameters for this endpoint.

Response Body

Name Type Description
poolEntities object[] List of pool entities
└ poolEntityId integer Pool entity ID
└ name string Pool name

POST /api/v1/p/validator/checkIsOfac

Check whether one or more validator public keys are flagged as OFAC.

Code sample:

curl -X POST "$ETHGAS_BASE_URL/api/v1/p/validator/checkIsOfac?publicKeys=0xabc...,0xdef..."
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/validator/checkIsOfac"
params = {"publicKeys": "0xabc...,0xdef..."}

response = requests.post(url, params=params)
print(response.text)

Example response:

{
    "success": true,
    "data": {
        "ofacValidator": [
            "0xabc..."
        ]
    }
}

Request

Parameter Required Type Description
publicKeys YES string Comma-separated validator public keys (hex, max 100)

Response Body

Name Type Description
ofacValidator string[] Subset of publicKeys that are OFAC-flagged

POST /api/v1/validator/register

Validator registering their public key into Ethgas

Request

Parameter Required Type Description
publicKey YES byte Public key of the validator in hexadecimal.

Code Sample

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/validator/register?publicKey=0x123423abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef..."
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/register"


payload = {
    'publicKey': '0x123423abcdef1234567890abcdef1234567890a...'
}

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "available": true,
    "verified": false,
    "message": {
         "address": "0x1234567890abcdef1234567890abcdef12345678..."
    }
}

Response Body

Field Type Description
available bool Indicates whether the request succeeded.
verified bool Indicates if the validator is verified (present when available is true).
message string Verification message for validator to sign.

POST /api/v1/validator/verify

Verify validator public key by verifying with the signed message

Request

Parameter Required Type Description
publicKey YES string Public key of the validator in hexadecimal.
signature YES string Signature in hexadecimal.

Code Sample

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/validator/verify?publicKey=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef&signature=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/verify"

payload = {
    'publicKey': '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
    'signature': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'
}

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "result": 0,
    "description": "Success"
}

Response Body

Field Type Description
result int Ordinal value representing the outcome of the verification.
description String Human-readable message detailing the verification result.

POST /api/v1/validator/deregister

Validator deregistering their public key from Ethgas

Request

Parameter Required Type Description
publicKeys YES byte Comma separated public keys of the validator in hexadecimal.

Code Sample

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/validator/deregister?publicKey=0x123423abcdef1234567890abcdef1234567890,0x3459871234567890abcdef1234567890abcdef1234567890..."
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/deregister"


payload = {
    'publicKey': '0x123423abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef,0x2345876124567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'
}

headers = {
    'Authorization': 'Bearer {{access_token}}',
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true
}

Response Body

Field Type Description
success boolean Whether API call is successful or not

GET /api/v1/validator/fees

Retrieve the list of fee payouts for a given validator key.

Code samples

curl -X GET "https://prod-mainnet.ethgas.com/api/v1/validator/fees?publicKey=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" \
     -H "Authorization: Bearer {{access_token}}"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/fees"

headers = {
  'Authorization': 'Bearer {{access_token}}'
}
params = {"publicKey": "0x" + "11" * 48}

response = requests.get(url, params=params, headers=headers)

print(response.json())

Example response:

{
    "success": true,
    "data": {
        "fees": [
            {
                "slot": 123456,
                "accountId": 1234,
                "publicKey": "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b",
                "validatorPayoutAddress": "0x123463a4b065722e99115d6c222f267d9cabb524",
                "quantity": "0.002850675",
                "txHash": "0x7f1911fc93c5886b29ff39d044d2d17f471795f3d15bf5cd8d093e3a92ee248e",
                "amount": "0.00285067499895",
                "gasFee": "0.00000000000105",
                "updateDate": 1766024399000,
                "batchPayoutSlots": []
            }
        ]
    }
}

Get list of validator fees.

Request

Parameter Required Type Description
publicKey NO string public key for validators
startSlot NO integer start slot number
limit NO integer Max number of records to return
asc NO boolean true for asc order, default to false for desc order

Response Body

Name Type Description
fees arrary of object List of validator fee objects
└ slot integer Slot number of the block
└ accountId integer Unique ID for each of the user's current & trading accounts assigned by ETHGas
└ publicKey string Public key of the validator in hexadecimal.
└ validatorPayoutAddress string Address of the fee recipient in hexadecimal.
└ txHash string Transaction hash of payout transaction
└ quantity string Payout quantity of the slot in Eth
└ amount string Payout amount in payout transaction in Eth.
└ gasFee string Gas fee charged in payout transaction
└ updateDate integer Last updated timestamp
└ batchPayoutSlots integer[] Included previous slots .
Notes

POST /api/v1/validator/onchain/payout

Enable or disable on-chain fee payouts for the authenticated user’s validator.

Code samples

curl -X POST "https://prod-mainnet.ethgas.com/api/v1/validator/onchain/payout?enable=0" \
     -H "Authorization: Bearer {{access_token}}"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/onchain/payout"
headers = {
  'Authorization': 'Bearer {{access_token}}'
}

params = {"enable": 0}

response = requests.post(url, params=params, headers=headers)
print(response.json())

Example response:

{
    "success": true,
    "data": {}
}

Enable or disable on-chain fee payout for user’s validators.

Request

Name Type Description
enable boolean Whether onchain payout is enabled for the user's validators. Default = true

Response Body

Name Type Description
success boolean Whether API call is successful or not
data object Response body (empty on success)

GET /api/v1/validator/mode

Retrieve the trading mode for the authenticated user's preconf account.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/validator/mode"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/mode"
headers = {
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers)
print(response.text)

Example response:

{
    "success": true,
    "data": {
        "mode": 0
    }
}

Request

No parameters for this endpoint.

Response Body

Name Type Description
mode integer Account trading mode. 0 = max-profit, 1 = light mode
Notes

POST /api/v1/validator/mode/enable

Enable light mode for the authenticated user's preconf account. This endpoint can only enable light mode; it cannot disable it or switch back to max-profit.

Optional publicKeys also enable light mode on matching validators owned by the user (regular, SSV, and Obol keys). Keys the user does not own are left unchanged. At most 100 keys may be sent in one request. Fails with USER_LOCKED if the user has locked their account.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "/api/v1/validator/mode/enable?publicKeys=0xabc...,0xdef..."
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/mode/enable"
headers = {"Authorization": "Bearer {{access_token}}"}
params = {"publicKeys": "0xabc...,0xdef..."}

response = requests.post(url, headers=headers, params=params)
print(response.text)

Example response:

{
    "success": true,
    "data": {
        "mode": 1
    }
}

Request

Parameter Required Type Description
publicKeys NO string Comma-separated validator public keys (hex, with or without 0x, max 100). If omitted, only the account setting is enabled

Response Body

Name Type Description
mode integer Account trading mode after the update. Always 1 (light mode) on success

Error Codes

Code Description
COMMON_NO_ACCOUNT Authenticated user has no in-preconf account
INVALID_PUBLIC_KEY Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request
USER_LOCKED User account is locked
Notes

POST /api/v1/validator/update/ofac

Update OFAC flag for the authenticated user’s validators.

If publicKeys is omitted, it updates all validators for the user.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/validator/update/ofac?publicKeys=0xabc...,0xdef...&ofac=true"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/update/ofac"
headers = {"Authorization": "Bearer {{access_token}}"}
params = {"publicKeys": "0xabc...,0xdef...", "ofac": True}

response = requests.post(url, headers=headers, params=params)
print(response.text)

Example response:

{
    "success": true,
    "data": {}
}

Request

Parameter Required Type Description
publicKeys YES string Explicit comma-separated validator keys, max 100. Missing/blank keys are rejected; update-all is not supported.
ofac NO boolean OFAC flag (default: false)

Response Body

Name Type Description
success boolean Whether API call is successful or not
data object Response body (empty on success)

Error Codes

Code Description
INVALID_PUBLIC_KEY Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request

POST /api/v1/validator/verify/batch

Verify multiple validator BLS signatures in one request.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/validator/verify/batch?publicKeys=0xabc...,0xdef...&signatures=0xsig1...,0xsig2..."
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/verify/batch"
headers = {"Authorization": "Bearer {{access_token}}"}
params = {
  "publicKeys": "0xabc...,0xdef...",
  "signatures": "0xsig1...,0xsig2..."
}

response = requests.post(url, headers=headers, params=params)
print(response.text)

Example response:

{
    "success": true,
    "data": {
        "0xabc...": { "result": 0, "description": "Success" },
        "0xdef...": { "result": 2, "description": "Invalid signature" }
    }
}

Request

Parameter Required Type Description
publicKeys YES string Comma-separated validator public keys (hex, max 100)
signatures YES string Comma-separated BLS signatures (hex), must match publicKeys count

Response Body

Name Type Description
data object Map of publicKey to verification result

Error Codes

Code Description
INVALID_PUBLIC_KEY Invalid validator public key format
INVALID_SIGNATURE Invalid signature format
VALIDATOR_SIGNATURE_SIZE_NOT_MATCH_PUBLIC_KEY publicKeys and signatures size mismatch
VALIDATOR_SIGNATURE_MAX Too many signatures (max 100)

POST /api/v1/validator/update/validatorPayoutAddress

publicKeys is required for both setting and clearing payout addresses. Supply 1–100 comma-separated keys, each exactly 48 bytes (96 hex digits, optional 0x prefix). Missing/blank keys, invalid hex, incorrect lengths and empty list elements return INVALID_PUBLIC_KEY; more than 100 keys returns VALIDATORS_MAX. These are application validation failures, not retryable server errors.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "/api/v1/validator/update/validatorPayoutAddress?publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890&validatorPayoutAddress=0x1234567890abcdef1234567890abcdef12345678"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/validator/update/validatorPayoutAddress"

payload = {
    'publicKeys': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
    'validatorPayoutAddress': '0x1234567890abcdef1234567890abcdef12345678'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)
curl -H "Authorization: Bearer {{access_token}}" -X POST "/api/v1/validator/update/validatorPayoutAddress?publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890&disable=true"

Example response:

{
    "success": true,
    "data": {}
}

Update validator payout address for a targeted set of regular validators. Only validators registered and owned by the authenticated user are updated; unregistered or non-owned keys are silently ignored.

Fails with USER_LOCKED if the user has locked their account.

Request

Parameter Required Type Description
publicKeys YES String Comma-separated list of validator public keys (hex format, max 100). Required; update-all is not supported
validatorPayoutAddress NO String Ethereum address to set as the payout address for matched validators
disable NO Boolean Set to true to clear validatorPayoutAddress for matched validators

Response Body

Name Type Description
success boolean Operation success status

Error Codes

Code Description
INVALID_PUBLIC_KEY publicKeys is missing, blank, malformed, or contains an invalid key
VALIDATORS_MAX More than 100 keys supplied
INVALID_ADDRESS validatorPayoutAddress is invalid, or the request provides neither validatorPayoutAddress nor disable=true, or both at the same time
USER_LOCKED User account is locked

SSV Validator

POST /api/v1/user/ssv/operator/register

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/ssv/operator/register?ownerAddress=0x1234567890123456789012345678901234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operator/register"

payload = {
    'ownerAddress': '0x1234567890123456789012345678901234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "available": true,
        "messageToSign": "Register SSV operator: 0x1234567890123456789012345678901234567890"
    }
}

Request verification for SSV operator registration.

Request

Parameter Required Type Description
ownerAddress YES String SSV operator owner address (hex format)

Response Body

Name Type Description
available boolean Whether the operator address is available for registration
messageToSign string Message to sign for verification

Error Codes

Code Description
SSV_OPERATOR_INVALID_ADDRESS Invalid operator address format

POST /api/v1/user/ssv/operator/deregister

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/ssv/operator/deregister?ownerAddress=0x1234567890123456789012345678901234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operator/deregister"

payload = {
    'ownerAddress': '0x1234567890123456789012345678901234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {}
}

Deregister an SSV operator.

Request

Parameter Required Type Description
ownerAddress YES String SSV operator owner address (hex format)

Response Body

Name Type Description
success boolean Operation success status

Error Codes

Code Description
SSV_OPERATOR_INVALID_ADDRESS Invalid operator address format
SSV_OPERATOR_NOT_REGISTERED Operator is not registered

POST /api/v1/user/ssv/operator/verify

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/ssv/operator/verify?ownerAddress=0x1234567890123456789012345678901234567890&signature=0x1234567890abcdef&autoImport=1&sync=1"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operator/verify"

payload = {
    'ownerAddress': '0x1234567890123456789012345678901234567890',
    'signature': '0x1234567890abcdef',
    'autoImport': '1',
    'sync': '1'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response (with sync=1):

{
    "success": true,
    "data": {
        "validators": [
            "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        ]
    }
}

Example response (with sync=0):

{
    "success": true,
    "data": {}
}

Verify SSV operator signature and complete registration.

Request

Parameter Required Type Description
ownerAddress YES String SSV operator owner address (hex format)
signature YES String Signature of the message to sign (hex format)
autoImport NO Boolean Whether to automatically import validators (default: false)
sync NO Boolean Whether to return validator list in response (default: false)

Response Body

Name Type Description
validators string[] List of validator public keys (only returned when sync=true)

Error Codes

Code Description
SSV_OPERATOR_INVALID_ADDRESS Invalid operator address format
SSV_OPERATOR_INVALID_SIGNATURE Invalid signature format or verification failed

POST /api/v1/user/ssv/operator/verifyByTx

Verify SSV operator registration using an on-chain transaction hash.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/ssv/operator/verifyByTx?ownerAddress=0x1234567890123456789012345678901234567890&txHash=0xabc...&autoImport=1&sync=1"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operator/verifyByTx"
headers = {"Authorization": "Bearer {{access_token}}"}
params = {
  "ownerAddress": "0x1234567890123456789012345678901234567890",
  "txHash": "0xabc...",
  "autoImport": True,
  "sync": True
}

response = requests.post(url, headers=headers, params=params)
print(response.text)

Example response (with sync=1):

{
    "success": true,
    "data": {
        "validators": [
            "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        ]
    }
}

Example response (with sync=0):

{
    "success": true,
    "data": {}
}

Request

Parameter Required Type Description
ownerAddress YES String SSV operator owner address (hex format)
txHash YES String Transaction hash (hex)
autoImport NO Boolean Whether to automatically import validators (default: false)
sync NO Boolean Whether to return validator list in response (default: false)

Response Body

Name Type Description
validators string[] List of validator public keys (only returned when sync=true)

Error Codes

Code Description
SSV_OPERATOR_INVALID_ADDRESS Invalid operator address format
SSV_OPERATOR_NOT_REGISTERED Operator is not registered
SSV_OPERATOR_INVALID_TX Transaction hash is invalid
SSV_OPERATOR_TX_NOT_FOUND Transaction not found

GET /api/v1/user/ssv/operators

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/ssv/operators"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operators"

payload = {}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "ssvOperators": [
            {
                "ownerId": 1,
                "userId": 73,
                "ownerAddress": "0x1234567890123456789012345678901234567890"
            }
        ]
    }
}

List all SSV operators for the current user.

Request

No parameters required.

Response Body

Name Type Description
ssvOperators object[] List of SSV operator objects
└ ownerId integer Unique owner ID
└ userId integer User ID associated with the operator
└ ownerAddress string Operator owner address (hex format)

POST /api/v1/user/ssv/operator/validator/register

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/ssv/operator/validator/register?ownerAddress=0x1234567890123456789012345678901234567890&publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890,0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operator/validator/register"

payload = {
    'ownerAddress': '0x1234567890123456789012345678901234567890',
    'publicKeys': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890,0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "validators": [
            "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        ]
    }
}

Register validators with an SSV operator. If no publicKeys are provided, it will refresh the validator list from the SSV network.

Request

Parameter Required Type Description
ownerAddress YES String SSV operator owner address (hex format)
publicKeys NO String Comma-separated list of validator public keys (hex format, max 100). If not provided, refreshes validator list from SSV network

Response Body

Name Type Description
validators string[] List of successfully added validator public keys

Error Codes

Code Description
SSV_OPERATOR_INVALID_ADDRESS Invalid operator address format
SSV_OPERATOR_NOT_REGISTERED Operator is not registered
SSV_VALIDATORS_REQUIRED At least one validator public key is required
SSV_VALIDATORS_INVALID Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request

POST /api/v1/user/ssv/operator/validator/deregister

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/ssv/operator/validator/deregister?ownerAddress=0x1234567890123456789012345678901234567890&publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operator/validator/deregister"

payload = {
    'ownerAddress': '0x1234567890123456789012345678901234567890',
    'publicKeys': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "removed": [
            "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        ]
    }
}

Deregister validators from an SSV operator. If no publicKeys are provided, it will remove all validators for the operator.

Request

Parameter Required Type Description
ownerAddress YES String SSV operator owner address (hex format)
publicKeys NO String Comma-separated list of validator public keys (hex format, max 100). If not provided, removes all validators for the operator

Response Body

Name Type Description
removed string[] List of successfully removed validator public keys

Error Codes

Code Description
SSV_OPERATOR_INVALID_ADDRESS Invalid operator address format
SSV_OPERATOR_NOT_REGISTERED Operator is not registered
SSV_VALIDATORS_REQUIRED At least one validator public key is required
SSV_VALIDATORS_INVALID Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request

GET /api/v1/user/ssv/operator/validators

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/ssv/operator/validators?ownerAddress=0x1234567890123456789012345678901234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operator/validators"

payload = {
    'ownerAddress': '0x1234567890123456789012345678901234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "validators": [
            "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        ]
    }
}

List validators for a specific SSV operator.

Request

Parameter Required Type Description
ownerAddress YES String SSV operator owner address (hex format)

Response Body

Name Type Description
validators string[] List of validator public keys (hex format)

Error Codes

Code Description
SSV_OPERATOR_INVALID_ADDRESS Invalid operator address format
SSV_OPERATOR_NOT_REGISTERED Operator is not registered

POST /api/v1/ssv/validator/mode/enable

Enable light mode for the authenticated user's preconf account. This endpoint can only enable light mode; it cannot disable it or switch back to max-profit.

Optional publicKeys also enable light mode on matching SSV validators owned by the user. Regular and Obol keys are not updated here (use POST /api/v1/validator/mode/enable or POST /api/v1/obol/validator/mode/enable). Keys the user does not own are left unchanged. At most 100 keys may be sent in one request. Fails with USER_LOCKED if the user has locked their account.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "/api/v1/ssv/validator/mode/enable?publicKeys=0xabc...,0xdef..."
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/ssv/validator/mode/enable"
headers = {"Authorization": "Bearer {{access_token}}"}
params = {"publicKeys": "0xabc...,0xdef..."}

response = requests.post(url, headers=headers, params=params)
print(response.text)

Example response:

{
    "success": true,
    "data": {
        "mode": 1
    }
}

Request

Parameter Required Type Description
publicKeys NO string Comma-separated SSV validator public keys (hex, with or without 0x, max 100). If omitted, only the account setting is enabled

Response Body

Name Type Description
mode integer Account trading mode after the update. Always 1 (light mode) on success

Error Codes

Code Description
COMMON_NO_ACCOUNT Authenticated user has no in-preconf account
INVALID_PUBLIC_KEY Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request
USER_LOCKED User account is locked
Notes

POST /api/v1/user/ssv/operator/validator/update/ofac

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/ssv/operator/validator/update/ofac?publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890&ofac=true"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operator/validator/update/ofac"

payload = {
    'publicKeys': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
    'ofac': 'true'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {}
}

Update OFAC flag for SSV validators.

Request

Parameter Required Type Description
publicKeys YES string Explicit comma-separated validator keys, max 100. Missing/blank keys are rejected; update-all is not supported.
ofac NO Boolean OFAC compliance flag (default: false)

Response Body

Name Type Description
success boolean Operation success status

Error Codes

Code Description
INVALID_PUBLIC_KEY Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request

POST /api/v1/user/ssv/operator/validator/update/validatorPayoutAddress

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "/api/v1/user/ssv/operator/validator/update/validatorPayoutAddress?publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890&validatorPayoutAddress=0x1234567890abcdef1234567890abcdef12345678"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/ssv/operator/validator/update/validatorPayoutAddress"

payload = {
    'publicKeys': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
    'validatorPayoutAddress': '0x1234567890abcdef1234567890abcdef12345678'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)
curl -H "Authorization: Bearer {{access_token}}" -X POST "/api/v1/user/ssv/operator/validator/update/validatorPayoutAddress?publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890&disable=true"

Example response:

{
    "success": true,
    "data": {}
}

Update validator payout address for a targeted set of SSV validators. Only validators registered and owned by the authenticated user are updated; unregistered or non-owned keys are silently ignored.

Fails with USER_LOCKED if the user has locked their account.

Request

Parameter Required Type Description
publicKeys YES String Comma-separated list of SSV validator public keys (hex format, max 100). Required; update-all is not supported
validatorPayoutAddress NO String Ethereum address to set as the payout address for matched validators
disable NO Boolean Set to true to clear validatorPayoutAddress for matched validators

Response Body

Name Type Description
success boolean Operation success status

Error Codes

Code Description
INVALID_PUBLIC_KEY publicKeys is missing, blank, malformed, or contains an invalid key
VALIDATORS_MAX More than 100 keys supplied
INVALID_ADDRESS validatorPayoutAddress is invalid, or the request provides neither validatorPayoutAddress nor disable=true, or both at the same time
USER_LOCKED User account is locked

Obol Validator

POST /api/v1/user/obol/operator/register

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/obol/operator/register?operatorAddress=0x1234567890123456789012345678901234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operator/register"

payload = {
    'operatorAddress': '0x1234567890123456789012345678901234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "available": true,
        "messageToSign": "Register Obol operator: 0x1234567890123456789012345678901234567890"
    }
}

Request verification for Obol operator registration.

Request

Parameter Required Type Description
operatorAddress YES String Obol operator address (hex format)

Response Body

Name Type Description
available boolean Whether the operator address is available for registration
messageToSign string Message to sign for verification

Error Codes

Code Description
OBOL_OPERATOR_INVALID_ADDRESS Invalid operator address format

POST /api/v1/user/obol/operator/deregister

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/obol/operator/deregister?operatorAddress=0x1234567890123456789012345678901234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operator/deregister"

payload = {
    'operatorAddress': '0x1234567890123456789012345678901234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {}
}

Deregister an Obol operator.

Request

Parameter Required Type Description
operatorAddress YES String Obol operator address (hex format)

Response Body

Name Type Description
success boolean Operation success status

Error Codes

Code Description
OBOL_OPERATOR_INVALID_ADDRESS Invalid operator address format

POST /api/v1/user/obol/operator/verify

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/obol/operator/verify?operatorAddress=0x1234567890123456789012345678901234567890&signature=0x1234567890abcdef&autoImport=1"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operator/verify"

payload = {
    'operatorAddress': '0x1234567890123456789012345678901234567890',
    'signature': '0x1234567890abcdef',
    'autoImport': '1'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
  "success": true,
  "data": {
    "operator": {
      "operatorId": 1,
      "userId": 73,
      "address": "0x1234567890123456789012345678901234567890",
      "ofac": false,
      "accountId": 2170,
      "collateralPerSlot": "10.5"
    }
  }
}

Verify Obol operator signature and complete registration.

Request

Parameter Required Type Description
operatorAddress YES String Obol operator address (hex format)
signature YES String Signature of the message to sign (hex format)
autoImport NO Boolean Whether to automatically import cluster definitions (default: false)

Response Body

Name Type Description
operator object Registered operator object
└ operatorId integer Unique operator ID
└ userId integer User ID associated with the operator
└ address string Operator address (hex format)
└ ofac boolean OFAC compliance status
└ accountId integer Associated account ID
└ collateralPerSlot string Collateral per slot amount
└ validatorKey string Validator key (if any)
└ clusterId integer Cluster ID (if any)

Error Codes

Code Description
OBOL_OPERATOR_INVALID_ADDRESS Invalid operator address format
OBOL_OPERATOR_INVALID_SIGNATURE Invalid signature format or verification failed

POST /api/v1/user/obol/operator/refresh

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/obol/operator/refresh?operatorAddress=0x1234567890123456789012345678901234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operator/refresh"

payload = {
    'operatorAddress': '0x1234567890123456789012345678901234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "clusters": {
            "0xabcdef1234567890": {
                "clusterId": 1,
                "config": "0x1234567890abcdef",
                "operators": ["0x1234567890123456789012345678901234567890"],
                "distributedValidatorKeys": ["0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"]
            }
        }
    }
}

Refresh Obol operator cluster definitions.

Request

Parameter Required Type Description
operatorAddress YES String Obol operator address (hex format)

Response Body

Name Type Description
clusters object Map of cluster definitions
└ [clusterKey] object Cluster definition object
└└ clusterId integer Unique cluster ID
└└ config string Cluster configuration (hex format)
└└ operators string[] List of operator addresses
└└ distributedValidatorKeys string[] List of distributed validator keys

Error Codes

Code Description
OBOL_OPERATOR_INVALID_ADDRESS Invalid operator address format

GET /api/v1/user/obol/operators

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/obol/operators"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operators"

payload = {}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=payload)

print(response.text)

Example response:

{
  "success": true,
  "data": {
    "operators": [
      {
        "operatorId": 1,
        "userId": 73,
        "address": "0x1234567890123456789012345678901234567890",
        "ofac": false,
        "accountId": 2170,
        "collateralPerSlot": "10.5",
        "clusterId": 1
      }
    ]
  }
}

List all Obol operators for the current user.

Request

No parameters required.

Response Body

Name Type Description
operators object[] List of operator objects
└ operatorId integer Unique operator ID
└ userId integer User ID associated with the operator
└ address string Operator address (hex format)
└ ofac boolean OFAC compliance status
└ accountId integer Associated account ID
└ collateralPerSlot string Collateral per slot amount
└ validatorKey string Validator key (if any)
└ clusterId integer Cluster ID (if any)

GET /api/v1/user/obol/operator/validators

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X GET "$ETHGAS_BASE_URL/api/v1/user/obol/operator/validators?operatorAddress=0x1234567890123456789012345678901234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operator/validators"

payload = {
    'operatorAddress': '0x1234567890123456789012345678901234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.get(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "validators": [
            "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        ]
    }
}

List validators for a specific Obol operator.

Request

Parameter Required Type Description
operatorAddress YES String Obol operator address (hex format)

Response Body

Name Type Description
validators string[] List of validator public keys (hex format)

Error Codes

Code Description
OBOL_OPERATOR_INVALID_ADDRESS Invalid operator address format

POST /api/v1/user/obol/operator/validator/register

Supported registration scopes: supply publicKeys to register selected keys, or omit it to import all available keys under the operator. Both modes are intentional API features. An empty string is not the same as omission.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/obol/operator/validator/register?operatorAddress=0x1234567890123456789012345678901234567890&publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890,0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operator/validator/register"

payload = {
    'operatorAddress': '0x1234567890123456789012345678901234567890',
    'publicKeys': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890,0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "added": [
            "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        ]
    }
}

Register validators with an Obol operator.

Request

Parameter Required Type Description
operatorAddress YES String Obol operator address (hex format)
publicKeys NO string Comma-separated keys, max 100 when supplied. Omission imports all available keys for this operator.

Response Body

Name Type Description
added string[] List of successfully added validator public keys

Error Codes

Code Description
OBOL_OPERATOR_INVALID_ADDRESS Invalid operator address format
OBOL_VALIDATORS_REQUIRED At least one validator public key is required
OBOL_VALIDATORS_INVALID Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request

POST /api/v1/user/obol/operator/validator/deregister

Supported deregistration scopes: supply publicKeys to deregister selected keys, or omit it to deregister all registered keys under the operator. Both modes are intentional API features. For all keys, send operatorAddress without a publicKeys parameter. An empty string is not the same as omission.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/obol/operator/validator/deregister?operatorAddress=0x1234567890123456789012345678901234567890&publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operator/validator/deregister"

payload = {
    'operatorAddress': '0x1234567890123456789012345678901234567890',
    'publicKeys': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "removed": [
            "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        ]
    }
}

Deregister validators from an Obol operator.

Request

Parameter Required Type Description
operatorAddress YES String Obol operator address (hex format)
publicKeys NO string Comma-separated keys, max 100 when supplied. Omission removes all registered keys for this operator.

Response Body

Name Type Description
removed string[] List of successfully removed validator public keys

Error Codes

Code Description
OBOL_OPERATOR_INVALID_ADDRESS Invalid operator address format
OBOL_VALIDATORS_REQUIRED At least one validator public key is required
OBOL_VALIDATORS_INVALID Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request

POST /api/v1/obol/validator/mode/enable

Enable light mode for the authenticated user's preconf account. This endpoint can only enable light mode; it cannot disable it or switch back to max-profit.

Optional publicKeys also enable light mode on matching Obol validators owned by the user. Regular and SSV keys are not updated here (use POST /api/v1/validator/mode/enable or POST /api/v1/ssv/validator/mode/enable). Keys the user does not own are left unchanged. At most 100 keys may be sent in one request. Fails with USER_LOCKED if the user has locked their account.

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "/api/v1/obol/validator/mode/enable?publicKeys=0xabc...,0xdef..."
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/obol/validator/mode/enable"
headers = {"Authorization": "Bearer {{access_token}}"}
params = {"publicKeys": "0xabc...,0xdef..."}

response = requests.post(url, headers=headers, params=params)
print(response.text)

Example response:

{
    "success": true,
    "data": {
        "mode": 1
    }
}

Request

Parameter Required Type Description
publicKeys NO string Comma-separated Obol validator public keys (hex, with or without 0x, max 100). If omitted, only the account setting is enabled

Response Body

Name Type Description
mode integer Account trading mode after the update. Always 1 (light mode) on success

Error Codes

Code Description
COMMON_NO_ACCOUNT Authenticated user has no in-preconf account
INVALID_PUBLIC_KEY Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request
USER_LOCKED User account is locked
Notes

POST /api/v1/user/obol/operator/validator/update/ofac

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "$ETHGAS_BASE_URL/api/v1/user/obol/operator/validator/update/ofac?publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890&ofac=true"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operator/validator/update/ofac"

payload = {
    'publicKeys': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
    'ofac': 'true'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)

Example response:

{
    "success": true,
    "data": {}
}

Update OFAC flag for Obol validators.

Request

Parameter Required Type Description
publicKeys YES string Explicit comma-separated validator keys, max 100. Missing/blank keys are rejected; update-all is not supported.
ofac YES Boolean OFAC compliance flag

Response Body

Name Type Description
success boolean Operation success status

Error Codes

Code Description
INVALID_PUBLIC_KEY Invalid validator public key format
VALIDATORS_MAX Maximum 100 validators allowed per request

POST /api/v1/user/obol/operator/validator/update/validatorPayoutAddress

Code sample:

curl -H "Authorization: Bearer {{access_token}}" -X POST "/api/v1/user/obol/operator/validator/update/validatorPayoutAddress?publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890&validatorPayoutAddress=0x1234567890abcdef1234567890abcdef12345678"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/user/obol/operator/validator/update/validatorPayoutAddress"

payload = {
    'publicKeys': '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
    'validatorPayoutAddress': '0x1234567890abcdef1234567890abcdef12345678'
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{access_token}}'
}

response = requests.post(url, headers=headers, params=payload)

print(response.text)
curl -H "Authorization: Bearer {{access_token}}" -X POST "/api/v1/user/obol/operator/validator/update/validatorPayoutAddress?publicKeys=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890&disable=true"

Example response:

{
    "success": true,
    "data": {}
}

Update validator payout address for a targeted set of Obol validators. Only validators registered and owned by the authenticated user are updated; unregistered or non-owned keys are silently ignored.

Fails with USER_LOCKED if the user has locked their account.

Request

Parameter Required Type Description
publicKeys YES String Comma-separated list of Obol validator public keys (hex format, max 100). Required; update-all is not supported
validatorPayoutAddress NO String Ethereum address to set as the payout address for matched validators
disable NO Boolean Set to true to clear validatorPayoutAddress for matched validators

Response Body

Name Type Description
success boolean Operation success status

Error Codes

Code Description
INVALID_PUBLIC_KEY publicKeys is missing, blank, malformed, or contains an invalid key
VALIDATORS_MAX More than 100 keys supplied
INVALID_ADDRESS validatorPayoutAddress is invalid, or the request provides neither validatorPayoutAddress nor disable=true, or both at the same time
USER_LOCKED User account is locked

Dashboard

Block and payment history can change when a payout is sent again. Use the same filters on every page. Payment history returns the latest successful payment for each original slot. slotTime and paymentTime are UTC ISO-8601. Amounts are decimal strings. Hex values may omit 0x.

Dashboard routes are public. They are under /api/v1/p/ and do not require a token.

Timestamps (startTime, endTime) must be ISO-8601 strings (e.g. 2026-01-13T00:00:00Z). Invalid timestamps return SYSTEM_VALIDATION.

Validator usage guide

Common questions and where to find the answer:

I want to... Use
See my recent block proposals and their status GET /api/v1/p/dashboard/operator/blockHistory (pass validatorUserId or operatorName — whichever you have on hand, not both)
See my payout/payment history ordered by paying slot GET /api/v1/p/dashboard/operator/paymentHistory (pass validatorUserId or operatorName — whichever you have on hand, not both)

Tip: any endpoint that takes startTime/endTime will default sensibly if you omit them (usually "today" or "the last 180 days") — you don't need to compute a range just to get a quick look at current standing.

GET /api/v1/p/dashboard/operator/blockHistory

Code sample:

curl -X GET "https://prod-mainnet.ethgas.com/api/v1/p/dashboard/operator/blockHistory?validatorUserId=73&limit=10"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/dashboard/operator/blockHistory"

params = {
    "validatorUserId": 73,
    "limit": 10
}

headers = {
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
  "success": true,
  "data": {
    "data": [
      {
        "dvtType": "SSV",
        "blockTime": "2026-07-10T08:15:24Z",
        "slot": 9876543,
        "blockNum": 20456789,
        "slashingResponse": "Valid",
        "blockStatus": "Proposed",
        "poolName": "Not available",
        "dvt": 1,
        "builderName": "titanbuilder",
        "wholeBlockValue": "0.05123456",
        "blockReward": "0.04123456",
        "gasUsed": 12500000,
        "txNum": 185,
        "collateral": "1.00000000",
        "builderSubmissionTime": 350,
        "pendingPayout": "0.00000000",
        "txIncluded": true,
        "txHash": "0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123ab",
        "txValue": "0.04000000",
        "repaymentPending": false,
        "multiRelay": false,
        "realtime": false,
        "validatorUserId": 73,
        "operatorName": "MyOperator",
        "wholeBlockMarketStatus": 0,
        "payoutStatus": 10,
        "validatorPayoutAddress": "0x1234567890123456789012345678901234567890",
        "validatorSigningTime": 120
      }
    ]
  }
}

Get operator block history (public; no session required).

Request

Parameter Required Type Description
validatorUserId NO integer Validator user ID
operatorName NO string Operator name
slots NO string Comma-separated slot numbers
startTime NO string ISO-8601 start time
endTime NO string ISO-8601 end time
limit NO integer Max records (default: 100)
offset NO integer Pagination offset (default: 0)
repaymentPending NO boolean Filter (implementation-specific)
pendingPayoutOnly NO boolean Filter (implementation-specific)
underReview NO boolean Filter (implementation-specific)
missedOnly NO boolean Filter (implementation-specific)
publicKeys NO string Comma-separated validator pubkeys (hex; 0x optional)

Response Body

Name Type Description
data object[] List of block history entries
└ dvtType string DVT type (e.g. SSV, Obol), if applicable
└ blockTime string Block time (ISO-8601)
└ slot integer Slot number
└ blockNum integer Block number
└ slashingResponse string Block slashing status in market — see values below
└ blockStatus string Status shown to validators — see values below
└ poolName string Pool name, or Not available
└ dvt integer DVT flag
└ builderName string Builder name, or Not available
└ wholeBlockValue string Whole block value (ETH)
└ blockReward string Block reward (ETH)
└ gasUsed integer Gas used in the block
└ txNum integer Number of transactions in the block
└ collateral string Collateral amount
└ builderSubmissionTime integer Builder submission time (ms)
└ pendingPayout string Pending payout amount
└ slotsRepaid string Slots this payout was repaid across, if any
└ txIncluded boolean Whether the payout tx has been included
└ txHash string Payout transaction hash
└ txValue string Payout transaction value
└ repaymentPending boolean Whether repayment is pending
└ repaidInSlot integer Slot in which repayment occurred, if any
└ multiRelay boolean Whether this is a multi-relay block
└ realtime boolean Whether this row is a realtime (unsettled) entry
└ validatorUserId integer Validator user ID
└ operatorName string Operator name
└ wholeBlockMarketStatus integer Whole-block market status code
└ payoutStatus integer Payout status code
└ validatorPayoutAddress string Validator payout address (hex)
└ validatorSigningTime integer Validator signing time (ms)
└ resendPayoutSlots string Slots on which the payout was resent, if any

blockStatus values:

Value Meaning
Pending Block outcome not yet finalized
Missed Validator missed the slot
Proposed Block was successfully proposed

Note: blockStatus (shown to validators) is a simplified 3-value status. slashingResponse (block slashing status in market) is a separate, more granular field with its own values: Missed, Vanilla Block, Invalid, Valid, Not Sold.

GET /api/v1/p/dashboard/operator/paymentHistory

Code sample:

curl -X GET "https://prod-mainnet.ethgas.com/api/v1/p/dashboard/operator/paymentHistory?validatorUserId=73&limit=10"

Resolve by operator name (matches display_name or verified_name):

curl -X GET "https://prod-mainnet.ethgas.com/api/v1/p/dashboard/operator/paymentHistory?operatorName=MyOperator&limit=10"

Filter payouts by paying-slot range (inclusive on both bounds):

curl -X GET "https://prod-mainnet.ethgas.com/api/v1/p/dashboard/operator/paymentHistory?validatorUserId=73&fromPaymentSlot=14755922&toPaymentSlot=14756468&limit=100"

Filter by original/paid slot(s), same comma-separated form as blockHistory slots:

curl -X GET "https://prod-mainnet.ethgas.com/api/v1/p/dashboard/operator/paymentHistory?validatorUserId=73&slots=14755922,14756468&limit=100"
import requests

url = "https://prod-mainnet.ethgas.com/api/v1/p/dashboard/operator/paymentHistory"

params = {
    "validatorUserId": 73,
    "limit": 10
}

headers = {
    'Content-Type': 'application/json'
}

response = requests.get(url, headers=headers, params=params)

print(response.text)

Example response:

{
    "success": true,
    "data": {
        "data": [
            {
                "slot": 14755922,
                "slotTime": "2026-07-10T08:15:24.000Z",
                "paymentSlot": 14756468,
                "paymentTime": "2026-07-10T12:33:59.000Z",
                "txHash": "B79D11F2746CE7C7D00049C75B929A316C4B3D342280402AC2395D9BA375AC5A",
                "txValue": "0.0220845434462",
                "validatorUserId": 73,
                "operatorName": "MyOperator",
                "validatorPayoutAddress": "1234567890123456789012345678901234567890"
            },
            {
                "slot": 14756468,
                "slotTime": "2026-07-10T12:33:59.000Z",
                "paymentSlot": 14756468,
                "paymentTime": "2026-07-10T12:33:59.000Z",
                "txHash": "B79D11F2746CE7C7D00049C75B929A316C4B3D342280402AC2395D9BA375AC5A",
                "txValue": "0.0220845434462",
                "validatorUserId": 73,
                "operatorName": "MyOperator",
                "validatorPayoutAddress": "1234567890123456789012345678901234567890"
            }
        ]
    }
}

Get paid payout history for a validator (public; no session required), ordered by paying slot then original slot (newest first by default). Pass validatorUserId and/or operatorName (filter matches user.display_name or user.verified_name). Response operatorName is COALESCE(verified_name, display_name) (same selection as blockHistory). Includes direct pays and resend/repay legs (including missed original slots that were repaid later). Sourced from validator_payout / validator_payout_eth_tx (not the ethereum sync materialization).

Request

Parameter Required Type Description
validatorUserId NO integer Validator user ID
operatorName NO string Filter by operator display_name or verified_name (same value matches either)
startTime NO string ISO-8601 lower bound on payment slot time (paymentTime)
endTime NO string ISO-8601 upper bound on payment slot time (paymentTime)
fromPaymentSlot NO integer Inclusive lower bound on paying slot (paymentSlot)
toPaymentSlot NO integer Inclusive upper bound on paying slot (paymentSlot)
slots NO string Comma-separated original/paid slot numbers (slot), same form as blockHistory
limit NO integer Max records (default: 100)
offset NO integer Pagination offset (default: 0)
asc NO boolean Sort ascending by paying slot, then original slot (default: false = newest first)
txHash NO string Filter to payments covered by this payout tx hash (32-byte hex; 0x prefix optional). A batch resend can return multiple rows.

Response Body

Name Type Description
data object[] List of payment history entries
└ slot integer Original proposal slot
└ slotTime string Consensus time of the original slot (ISO-8601)
└ paymentSlot integer Paying slot: original slot for a direct pay, or the later resend paying slot
└ paymentTime string Consensus time of paymentSlot (ISO-8601)
└ txHash string On-chain paying payout tx hash (hex, no 0x prefix)
└ txValue string Paying tx ETH amount
└ validatorUserId integer Validator user ID
└ operatorName string Operator name (COALESCE(verified_name, display_name), same as blockHistory)
└ validatorPayoutAddress string Validator payout address for the original market/slot (hex, no 0x prefix)

WEBSOCKET

Path

/ws

Stream public and private market data. Use the WebSocket base URL for your environment. Mainnet is wss://prod-mainnet.ethgas.com/ws. Hoodi is wss://hoodi.app.ethgas.com/ws.

# A sample python script to connect to our webserver to subscribe to different channels.

import json

import websocket
from websocket import WebSocket

__ws_url = "wss://prod-mainnet.ethgas.com/ws"


def on_open(ws: WebSocket):
    message = {
        "op": "subscribe",
        "args": [
            {
                "channel": "orderBookUpdate",
                "marketType": "wholeBlock"
            }
        ]
    }
    ws.send(json.dumps(message))


def on_message(ws: WebSocket, message: str):
    print(f"Received message: {message}")


def on_error(ws: WebSocket, error: Exception):
    print(f"Error: {error}")


def on_close(ws: WebSocket, close_status_code: int, close_msg: str):
    print("WebSocket closed")


if __name__ == "__main__":
    ws_app = websocket.WebSocketApp(
        __ws_url,
        on_open=on_open,
        on_message=on_message,
        on_close=on_close,
        on_error=on_error,
    )
    ws_app.run_forever()

Message Structure

Request

Field Required Type Description
op YES string operation type
args YES object[] list of operation arguments

Operation Types

Response

Command responses (login, subscribe, unsubscribe, error) use:

Field Type Description
event string Response event type
arg object Response payload for the command
code integer Result code
msg string Result message
connId string Connection ID

Stream responses use:

Field Type Description
e string Event type
E integer Event timestamp
s string Instrument ID
a string Action type, when applicable
P object Data of corresponding event type

Query responses use:

Field Type Description
q string Query type
s string Instrument ID, when applicable
P object Query payload

Commands

subscribe

Subscribe to one or multiple topics

{
    "op": "subscribe",
    "args": [
        {
            "channel": "preconfMarketUpdate",
            "marketType": "inclusionPreconf"
        },
        {
            "channel": "candlestickUpdate",
            "marketType": "wholeBlock"
        },
        {
            "channel": "recentTradeUpdate",
            "marketType": "inclusionPreconf"
        },
        {
            "channel": "orderBookUpdate",
            "marketType": "inclusionPreconf"
        },
        {
            "channel": "tickerUpdate",
            "marketType": "inclusionPreconf"
        },
        {
            "channel": "inclusionPreconfSaleUpdate"
        },
        {
            "channel": "blockBuilderUpdate"
        }
    ]
}

unsubscribe

Unsubscribe from one or multiple topics

{
    "op": "unsubscribe",
    "args": [
        {
            "channel": "preconfMarketUpdate",
            "marketType": "inclusionPreconf"
        },
        {
            "channel": "candlestickUpdate",
            "marketType": "wholeBlock"
        },
        {
            "channel": "recentTradeUpdate",
            "marketType": "inclusionPreconf"
        },
        {
            "channel": "orderBookUpdate",
            "marketType": "inclusionPreconf"
        },
        {
            "channel": "tickerUpdate",
            "marketType": "inclusionPreconf"
        },
        {
            "channel": "inclusionPreconfSaleUpdate"
        },
        {
            "channel": "blockBuilderUpdate"
        }
    ]
}

query

Query data from a topic

Example

{
    "op": "query",
    "args": [
        {
            "queryType": "currentSlot"
        },
        {
            "queryType": "preconfMarkets",
            "marketType": "inclusionPreconf"
        },
        {
            "queryType": "orderBook",
            "marketType": "wholeBlock"
        }
    ]
}

login

Login to the websocket server for acessing private channel/query

Example Request

{
    "op": "login",
    "args": [
        {
            "accessToken": "<access-or-refresh-token>"
        }
    ]
}

Example Response

{
    "event": "login",
    "code": 0,
    "msg": "",
    "connId": "25f9ee2c"
}

Channel

Within a channel, you can subscribe to topics needed to receive real time updates.

Public Channel

Preconf Market Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "preconfMarketUpdate",
            "marketType": "inclusionPreconf"
        }
    ]
}

Example Response

{
    "e": "preconfMarketUpdate",
    "E": 1744684899022,
    "s": "ETH-PC-603410",
    "a": "NewEpoch",
    "P": {
        "m": 1000000603410,
        "T": "inclusionPreconf",
        "s": 603410,
        "i": "ETH-PC-603410",
        "n": "Eth Preconf Inclusion Slot #603410",
        "M": 1744685494000,
        "f": 1744686266000,
        "b": 1744685498000,
        "q": "1",
        "mQ": "1",
        "MQ": "36000000",
        "PS": "0.00000000001",
        "mP": "0.00000000001",
        "MP": "0.00001",
        "C": "3.99996",
        "A": 36000000,
        "r": 0,
        "S": 0,
        "e": 1,
        "a": 1744685496000,
        "c": 1744684899000,
        "u": 1744684899000,
        "tp": 36000000,
        "mode": 0
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string channel name, e.g. preconfMarketUpdate`
└ marketType string Market type, e.g., inclusionPreconf`.

Response Body

Name Type Description
e string Event type, e.g.preconfMarketUpdate
E integer Event time in milliseconds.
s string Instrument ID of the market, e.g. ETH-PC-42093.
a string Action type, e.g. NewEpoch
P object Payload data containing market details.
└ m integer Market ID.
└ T string Market type, e.g. inclusionPreconf
└ s integer Slot ID.
└ i string Instrument ID.
└ n string Market name, e.g. Eth Preconf Inclusion Slot #42093.
└ M integer Market expiry time in milliseconds.
└ a integer Bundle submission deadline in milliseconds. (Optional)
└ f integer Block finality time in milliseconds.
└ b integer Block time in milliseconds.
└ mQ string Minimum order quantity allowed in the market. (Optional)
└ MQ string Maximum order quantity allowed in the market. (Optional)
└ q string Precision step of order quantity. (Optional)
└ PS string Precision step of order price.
└ mP string Minimum price allowed in the market.
└ MP string Maximum price allowed in the market.
└ p string Last traded price of the market
└ PC float Price change percentage.
└ d boolean Market direction.
└ BB string Best bid price.
└ BA string Best ask price.
└ o string Mid price.
└ C string Collateral per slot in ETH.
└ A integer Available preconf for sale.
└ r integer Block owner reserved preconf not for sale.
└ S integer Block owner submitted preconf not for sale.
└ e integer Market status.
└ c integer Market Creation time in milliseconds.
└ u integer Last market update time in milliseconds.
└ O boolean OFAC filtering enabled flag.
└ R boolean Realtime market flag.
└ te boolean Trading enabled flag.
└ mode integer Market trading mode. 0 = max-profit, 1 = light mode.
└ MT boolean Multi-relay market flag.
└ tp integer Total amount of preconf allowed to sell in the market
Notes

Candlestick Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "candlestickUpdate",
            "marketType": "inclusionPreconf"
        }
    ]
}

Example Response

{
    "e": "candlestickUpdate",
    "E": 1736742241012,
    "s": "ETH-PC-117",
    "P": {
        "I": "ETH-PC-117",
        "m": 1000000000117,
        "t": 1736742240000,
        "i": 1000,
        "o": "0",
        "h": "0",
        "l": "0",
        "c": "0",
        "v": "0",
        "F": true
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., candlestickUpdate`.
└ marketType string Market type, e.g., inclusionPreconf`.

Response Body

Name Type Description
e string Event type, e.g. candlestickUpdate.
E integer Event timestamp in milliseconds.
s string Instrument ID of the market, e.g., ETH-PC-117`.
P object Payload data containing market price history details.
└ I string Instrument ID, e.g., ETH-PC-117`.
└ m integer Market ID.
└ t integer Timestamp of the price data in milliseconds.
└ i integer Interval of the candlestick in milliseconds.
└ o string Open price during the interval.
└ h string High price during the interval.
└ l string Low price during the interval.
└ c string Close price during the interval.
└ v string Volume during the interval.
└ F boolean Indicates if the data is final (true) or incomplete (false).
Notes

Recent Trades Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "recentTradeUpdate",
            "marketType": "inclusionPreconf"
        }
    ]
}

Example Response

{
    "e": "recentTradeUpdate",
    "E": 1739528277074,
    "s": "ETH-PC-173649",
    "P": {
        "i": "ETH-PC-173649",
        "p": "0.00000000006",
        "q": "1702005",
        "s": true,
        "d": 1739528277070,
        "t": 683198
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., recentTradeUpdate
└ marketType string Market type, e.g., inclusionPreconf.

Response Body

Name Type Description
e string Event type, e.g., recentTradeUpdate.
E integer Event timestamp in milliseconds.
s string Instrument ID.
P object Payload data containing recent trades details.
└ i string Instrument ID .
└ p string Traded price of the trade
└ q string Traded quantity of the trade
└ s integer Trading side of taker
└ d integer Timestamp of the trade in milliseconds.
└ t integer Trade index.
Notes

Order Book Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "orderBookUpdate",
            "marketType": "inclusionPreconf"
        }
    ]
}

Example Response

{
    "e": "orderBookUpdate",
    "E": 1736751224943,
    "s": "ETH-PC-863",
    "P": {
        "a": [],
        "b": [
            {
                "p": "0.00000000005",
                "q": "5861476"
            }
        ],
        "I": "ETH-PC-863",
        "t": 1736751224941
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., orderBookUpdate.
└ marketType string Market type, e.g., inclusionPreconf.

Response Body

Name Type Description
e string Event type, e.g., orderBookUpdate.
E integer Event timestamp in milliseconds.
s string Instrument ID of the market, e.g., ETH-PC-863.
P object Payload data containing order book details.
└ a array List of ask orders (empty in the example).
└ b array List of bid orders.
└└ p string Price of the bid order.
└└ q string Quantity of the bid order.
└ I string Instrument ID, e.g., ETH-PC-863.
└ t integer Timestamp of the order book update in milliseconds.
Notes

Ticker Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "tickerUpdate",
            "marketType": "inclusionPreconf"
        }
    ]
}

Example Response

{
    "e": "tickerUpdate",
    "E": 1743667424734,
    "s": "ETH-PC-518598",
    "P": {
        "d": false,
        "p": "0.00000000002",
        "b": "0.00000000002",
        "M": "0.00000000002",
        "A": 18855242,
        "g": 17144758,
        "P": 1.0,
        "u": 1743667299000
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., tickerUpdate.
└ marketType string Market type, e.g., inclusionPreconf.

Response Body

Name Type Description
e string Event type, e.g., tickerUpdate.
E integer Event timestamp in milliseconds.
s string Instrument ID of the market, e.g., ETH-PC-856.
P object Payload data containing market information.
└ d boolean Market direction (true for buy, false for sell).
└ p string Last traded price.
└ b string Best bid price.
└ a string Best ask price.
└ M string Mid price in orderbook.
└ A string Available preconf gas amount in the slot.
└ g string Total gas purchased in the market. (optional)
└ P string Percentage price change in the market.
└ u integer Timestamp of the last update in milliseconds.
Notes

Inclusion Preconf Top Sales

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "inclusionPreconfSaleUpdate"
        }
    ]
}

Example Response

{
    "e": "inclusionPreconfSaleUpdate",
    "E": 1739765044256,
    "P": {
        "s": 193373,
        "g": "11288799",
        "S": [
            {
                "p": "0.0000000001",
                "q": "11078799"
            }
        ]
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., inclusionPreconfSaleUpdate.

Response Body

Name Type Description
e string Event type, e.g., inclusionPreconfSaleUpdate.
E integer Event timestamp in milliseconds.
P object Payload data containing block builder update details.
└ s integer slot
└ g string gas purchased
└ S array array of top 10 preconf sales
└└ p string purchased gas price
└└ q string gas unit
Notes

Block Builder Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "blockBuilderUpdate"
        }
    ]
}

Example Response

{
    "e": "blockBuilderUpdate",
    "E": 1739527942002,
    "a": "MarketExpiry",
    "P": {
        "s": 173614,
        "p": [
            "0x00000000000000000000000000000000caf14edec47d16536506af7a6d69eac6b1a66a042205f7ca768655a481038ae5"
        ],
        "f": "0xa1885d66bef164889a2e35845c3b626545d7b0e513efe335e97c3a45e534013fa3bc38c3b7e6143695aecc4872ac52c4"
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., blockBuilderUpdate.

Response Body

Name Type Description
e string Event type, e.g., blockBuilderUpdate
E integer Event timestamp in milliseconds.
a string Action type, e.g. MarketExpiry
P object Payload data containing block builder update details.
└ s integer slot ID.
└ p array Builder public keys of corresponding slot
└ f string Fallback builder public key
Notes

Private Channel

Account Order Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
             "channel": "accountOrderUpdate",
             "marketType": "inclusionPreconf"
        }
    ]
}

Example Response

{
    "e": "accountOrderUpdate",
    "E": 1742288403296,
    "s": "ETH-PC-403684",
    "P": {
        "o": 173639360,
        "c": "613ec528",
        "a": 2049,
        "C": 53,
        "t": 2,
        "i": "ETH-PC-403684",
        "m": 1000000403684,
        "p": "0.00000000001",
        "q": "3181683",
        "F": "3181683",
        "fp": "0.00003181683",
        "f": "0.0000028635147",
        "s": false,
        "P": false,
        "S": 10,
        "d": 1742288403289,
        "u": 1742288403289
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., accountOrderUpdate.
└ marketType string Market type, e.g., inclusionPreconf.

Response Body

Name Type Description
e string Event type, e.g., accountOrderUpdate
E integer Event timestamp in milliseconds.
P array Array of order objects.
└ o integer Order ID, e.g., 1234.
└ c string Client Order ID, e.g., 43f4159e.
└ a integer Account ID.
└ C integer User ID who created this order.
└ t boolean Order Type.
└ i string Instrument ID.
└ m integer Market Id.
└ p string Order price.
└ q string Order total quantity.
└ F string Order filled quantity .
└ fp string Order filled price * quantity.
└ f fee Order fee.
└ s boolean Order side.
└ P boolean Flag for post-only order.
└ S integer Order Status.
└ d integer Timestamp of order creation time.
└ u integer Timestamp of last update time.
Notes

Account Transaction Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "accountTransactionUpdate",
            "marketType": "inclusionPreconf"
        }
    ]
}

Example Response

{
    "e": "accountTransactionUpdate",
    "E": 1742288580882,
    "s": "ETH-PC-403699",
    "P": {
        "t": 146600149,
        "i": "ETH-PC-403699",
        "o": 173651088,
        "a": 2049,
        "s": true,
        "p": "0.00000000001",
        "q": "1248972",
        "f": "0.0000011240748",
        "d": 1742288580863
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., accountTransactionUpdate.
└ marketType string Market type, e.g., inclusionPreconf.

Response Body

Name Type Description
e string Event type, e.g., accountTransactionUpdate
E integer Event timestamp in milliseconds.
P object Payload data containing block builder update details.
s string Instrument ID, e.g., ETH-PC-403699.
└ t integer Transaction ID, e.g., 123456.
└ i string Instrument ID, e.g., ETH-PC-403699.
└ o integer Order ID of the trade executed, e.g., 123456.
└ a integer Account ID of the trade executed, e.g., 123.
└ s boolean Traded Side, e.g., true.
└ p string Traded price, e.g., 0.00000000001.
└ q string Traded quantity, e.g., 1248972.
└ f string Trading fee, e.g., 0.0000011240748.
└ d timestamp Timestamp of the trade execution, e.g., 1742288580863.
Notes

Account Position Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "accountPositionUpdate",
            "marketType": "inclusionPreconf"
        }
    ]
}

Example Response

{
    "e": "accountPositionUpdate",
    "E": 1742288402217,
    "P": {
        "a": 2049,
        "s": 403684,
        "m": 1,
        "q": "20427356",
        "l": "0",
        "p": "0",
        "e": false,
        "b": false,
        "c": 1742288355000,
        "u": 1742288402000,
        "A": "20427356"
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., accountPositionUpdate.
└ marketType string Market type, e.g., inclusionPreconf.

Response Body

Name Type Description
e string Event type, e.g., accountPositionUpdate
E integer Event timestamp in milliseconds.
P object Payload data containing account position update details.
└ a integer Account Id.
└ s integer Slot number of the position.
└ m integer Market type of the position.
└ q string Position's total quantity.
└ l string Position's locked quantity
└ p string Position purchased price.
└ e boolean Expired flag.
└ b boolean Builder fill enable flag.
└ c integer Position create timestamp.
└ u integer Position last updated timestamp.
└ A integer Position's available quantity.
Notes

Preconf Bundle Update

Example Request

{
    "op": "subscribe",
    "args": [
        {
            "channel": "preconfBundleUpdate"
        }
    ]
}

Example Response

{
    "e": "preconfBundleUpdate",
    "E": 1743674748083,
    "P": {
        "s": 519181,
        "e": 1260000,
        "bu": [
            {
                "u": "456a8e9d-ce47-421d-8135-9ed9680ab57e",
                "B": 1,
                "o": 1,
                "txs": [
                    {
                        "r": false,
                        "tx": "0x02f88b827e7e8302bcff8084773594008303345094f37512b7c630890c500b02724671cf3ae5607563843b9aca009b45746847617320496e636c7573696f6e20507265636f6e66732e20c001a007797cf3e30a7d45ef43ab9b76d309b76db5f3704cb4936890245b374bad5925a00ad6fa6556dd1448beaf39fc6c5faa097eaf615144905f7d60fb72b15ded30e4",
                        "h": "0x653304b826eca4f48510d29e8ac2a9fcad6ecf3ef3bc3ca3a837718f3d6fa368"
                    },
                    {
                        "r": false,
                        "tx": "0x02f88b827e7e8302bd008084773594008303345094f37512b7c630890c500b02724671cf3ae5607563843b9aca009b45746847617320496e636c7573696f6e20507265636f6e66732e20c080a03b1a7ca0651410d37aedef11740e4e902a9bcb106bcb3bb1f98f18d9ed2bda25a02fabfa492e172ac244cb809d0d035c75ed4b04e5f7e92258781e7cd55daabef9",
                        "h": "0x3076010ac7607ae41a9dacb14b55bba5a91ca4aad1189ed90e5adac638f7d43c"
                    }
                ],
                "p": "0.00000000597"
            }
        ],
        "r": "0x8f02425b5f3c522b7ef8ea124162645f0397c478"
    }
}

Request

Name Type Description
op string e.g. subscribe
args object Arguments
└ channel string Channel name, e.g., preconfBundleUpdate.

Response Body

Name Type Description
e string Event type, e.g., preconfBundleUpdate
E integer Event timestamp in milliseconds.
P object Payload data containing block builder update details.
└ s integer slot ID.
└ e integer Empty block space in the slot (For block owner only.)
└ bu array Array of preconf bundles in the slot.
└└ u string UUID of the bundle.
└└ p string Gas price of the bundle.
└└ txs array Array of transaction in the bundle
└└└ r boolean Whether this ethereum tranasaction can be reverted.
└└└ tx string Raw ethereum transaction data in the bundle
└└└ h string Transaction hash of transaction data
Notes

Query

In a websocket session, you can query public or private data using the query command.

Public Query

Preconf Markets Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "preconfMarkets",
            "marketType": "inclusionPreconf"
        }
    ]
}

Example Response

{
    "q": "preconfMarkets",
    "s": "ETH-PC-603391",
    "P": {
        "m": 1000000603391,
        "T": "inclusionPreconf",
        "s": 603391,
        "i": "ETH-PC-603391",
        "n": "Eth Preconf Inclusion Slot #603391",
        "M": 1744685266000,
        "f": 1744686038000,
        "b": 1744685270000,
        "q": "1",
        "mQ": "1",
        "MQ": "36000000",
        "PS": "0.00000000001",
        "mP": "0.00000000001",
        "MP": "0.00001",
        "d": false,
        "BB": "0.00000000001",
        "o": "0.00000000001",
        "C": "3.99996",
        "A": 36000000,
        "r": 0,
        "S": 0,
        "e": 1,
        "a": 1744685268000,
        "c": 1744684515000,
        "u": 1744684845000,
        "tp": 36000000
    }
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., preconfMarkets.
└ marketType string Market type, e.g., inclusionPreconf.

Response Body

Name Type Description
q string Query type, e.g., preconfMarkets.
s string Instrument ID of the market, e.g., ETH-PC-1151.
P object Payload data containing market information.
└ m integer Market ID.
└ T string Market type, e.g. inclusionPreconf
└ s integer Slot ID.
└ i string Instrument ID.
└ n string Market name, e.g. Eth Preconf Inclusion Slot #42093.
└ M integer Market expiry time in milliseconds.
└ a integer Bundle submission deadline in milliseconds. (Optional)
└ f integer Block finality time in milliseconds.
└ b integer Block time in milliseconds.
└ mQ string Minimum order quantity allowed in the market. (Optional)
└ MQ string Maximum order quantity allowed in the market. (Optional)
└ q string Precision step of order quantity. (Optional)
└ PS string Precision step of order price.
└ mP string Minimum price allowed in the market.
└ MP string Maximum price allowed in the market.
└ p string Last traded price of the market
└ PC float Price change percentage.
└ d boolean Market direction.
└ BB string Best bid price.
└ BA string Best ask price.
└ o string Mid price.
└ C string Collateral per slot in ETH.
└ A integer Available preconf for sale.
└ r integer Block owner reserved preconf not for sale.
└ S integer Block owner submitted preconf not for sale.
└ e integer Market status.
└ c integer Market Creation time in milliseconds.
└ u integer Last market update time in milliseconds.
└ tp integer Total amount of preconf allowed to sell in the market
Notes

Order Books Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "orderBook",
            "marketType": "wholeBlock"
        }
    ]
}

Example Response

{
    "q": "orderBook",
    "s": "ETH-WB-1535",
    "P": {
        "a": [],
        "b": [
            {
                "q": "1",
                "p": "0.00000000567"
            },
            {
                "q": "2",
                "p": "0.00000000566"
            }
        ],
        "t": 1736759161542,
        "I": "ETH-WB-1535"
    }
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., orderBook.
└ marketType string Market type, e.g., wholeBlock.

Response Body

Name Type Description
q string Query type, e.g., orderBook.
s string Instrument ID of the market, e.g., ETH-WB-1535.
P object Payload data containing order book information.
└ a array List of ask orders (empty in the example).
└ b array List of bid orders.
└└ q string Quantity of the bid order.
└└ p string Price of the bid order.
└ t integer Timestamp of the order book query in milliseconds.
└ I string Instrument ID, e.g., ETH-WB-1535.
Notes

Current Slot Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "currentSlot"
        }
    ]
}

Example Response

{
    "q": "currentSlot",
    "P": {
        "t": 1736759362264,
        "s": 1497,
        "r": 1736
    }
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., currentSlot.

Response Body

Name Type Description
q string Query type, e.g., currentSlot.
P object Payload data containing slot information.
└ t integer Timestamp of the current slot in milliseconds.
└ s integer Current slot ID.
└ r integer Remaining time to next slot in milliseconds.
Notes

Candlesticks Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "candlesticks",
            "interval": 1000,
            "instrumentId": "ETH-PC-1567"
        }
    ]
}

Example Response

{
    "q": "candlesticks",
    "s": "ETH-PC-1567",
    "P": [
        {
            "I": "ETH-PC-1567",
            "m": 1000000001567,
            "t": 1736759832000,
            "i": 1000,
            "o": "0.00000000009",
            "h": "0.00000000009",
            "l": "0.00000000009",
            "c": "0.00000000009",
            "v": "0",
            "F": false
        },
        {
            "I": "ETH-PC-1567",
            "m": 1000000001567,
            "t": 1736759831000,
            "i": 1000,
            "o": "0.00000000009",
            "h": "0.00000000009",
            "l": "0.00000000009",
            "c": "0.00000000009",
            "v": "0",
            "F": true
        },
        {
            "I": "ETH-PC-1567",
            "m": 1000000001567,
            "t": 1736759830000,
            "i": 1000,
            "o": "0.00000000008",
            "h": "0.00000000009",
            "l": "0.00000000008",
            "c": "0.00000000009",
            "v": "2912472",
            "F": true
        }
    ]
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., candlesticks.
└ interval integer Interval for price history in milliseconds, e.g., 1000.
└ instrumentId string Instrument ID to query price history, e.g., ETH-PC-1567.

Response Body

Name Type Description
q string Query type, e.g., candlesticks.
s string Instrument ID of the queried market, e.g., ETH-PC-1567.
P array Array of market price history objects.
└ I string Instrument ID, e.g., ETH-PC-1567.
└ m integer Market ID.
└ t integer Timestamp of the price data in milliseconds.
└ i integer Interval of the data.
└ o string Open price during the interval.
└ h string High price during the interval.
└ l string Low price during the interval.
└ c string Close price during the interval.
└ v string Volume during the interval.
└ F boolean Indicates if the data is final (true) or incomplete (false).
Notes

Recent Trades Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "recentTrades",
            "instrumentId": "ETH-PC-1567",
            "limit": 10
        }
    ]
}

Example Response

{
    "q": "recentTrades",
    "s": "ETH-PC-1567",
    "P": [
        {
            "i": "ETH-PC-1567",
            "p": "0.00000000021",
            "q": "1534591",
            "s": true,
            "d": 1736760078290,
            "t": 89130
        },
        {
            "i": "ETH-PC-1567",
            "p": "0.00000000021",
            "q": "270409",
            "s": false,
            "d": 1736760078369,
            "t": 89216
        }
    ],
    "l": 10
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., recentTrades.
└ instrumentId string Instrument ID, e.g., ETH-PC-1567.
└ limit integer (Optional) Maximum number of trades to return (default is 100).

Response Body

Name Type Description
q string Query type, e.g., recentTrades.
s string Instrument ID of the queried market, e.g., ETH-PC-1567.
l integer The limit applied to the query.
P array Array of recent trade objects.
└ i string Instrument ID, e.g., ETH-PC-1567.
└ p string Price at which the trade occurred.
└ q string Traded quantity .
└ s boolean Trade side (true for buy, false for sell).
└ d integer Timestamp of the trade in milliseconds.
└ t integer Trade ID.
Notes

Inclusion Preconf Top Sales Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "inclusionPreconfTopSales",
            "slot": 403973
        }
    ]
}

Example Response

{
    "q": "inclusionPreconfTopSales",
    "P": {
        "s": 403973,
        "g": 18662236,
        "S": [
            {
                "p": "0.00000000009",
                "q": "12662236"
            }
        ]
    }
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., inclusionPreconfTopSales.
└ slot integer (Optional) Slot to query. Uses next slot if omitted.

Response Body

Name Type Description
q string Query type, e.g., inclusionPreconfTopSales.
P object Payload data containing inclusion preconf top sales information.
└ s integer Slot ID.
└ g integer Total gas purchased in this slot.
└ S array Array of top gas sales.
└└ p string Purchased price in average
└└ q string Purchased gas quantity
Notes

Current Block Builder Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "currentBlockBuilder",
            "slot": 123456
        }
    ]
}

If you want the next slot's builder, omit the slot field:

{
    "op": "query",
    "args": [
        {
            "queryType": "currentBlockBuilder"
        }
    ]
}

Example Response

{
    "q": "currentBlockBuilder",
    "P": {
        "s": 402361,
        "p": [
            "0xA25ADDC4FC16F72CA667177D7A5533D4287B3574F0127FFC227095E90B0B1FD0DD48C421E04E613D2298FE4DAC83A2A5"
        ],
        "f": "0xa1885d66bef164889a2e35845c3b626545d7b0e513efe335e97c3a45e534013fa3bc38c3b7e6143695aecc4872ac52c4"
    }
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., currentBlockBuilder.
└ slot integer Slot, e.g., 123456. Optional. Use next slot if not specified.

Response Body

Name Type Description
q string Query type, e.g., currentBlockBuilder.
P object Payload data containing block builder information.
└ s integer slot.
└ p array Block builder public keys. Optional if market owner does not delegate a builder
└ f string Fallback builder public key.
Notes

Private Query

Open Orders Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "openOrders",
            "accountId": 1234,
            "instrumentId": "ETH-PC-123456",
            "startId": 0,
            "limit": 100
        }
    ]
}

Example Response


{
    "q": "openOrders",
    "s": "ETH-PC-194361",
    "P": [
        {
            "o": 61702036,
            "c": "43f4159e",
            "a": 2049,
            "C": 53,
            "t": 2,
            "i": "ETH-PC-194361",
            "m": 1000000194361,
            "p": "0.00000000001",
            "q": "1907125",
            "F": "1907125",
            "fp": "0.00001907125",
            "f": "0.0000017164125",
            "s": false,
            "P": false,
            "S": 10,
            "d": 1739776227777,
            "u": 1739776227777
        },
        {
            "o": 61702196,
            "c": "454057b4",
            "a": 2049,
            "C": 53,
            "t": 2,
            "i": "ETH-PC-194361",
            "m": 1000000194361,
            "p": "0.00000000001",
            "q": "1864896",
            "F": "1864896",
            "fp": "0.00001864896",
            "f": "0.0000016784064",
            "s": false,
            "P": false,
            "S": 10,
            "d": 1739776229952,
            "u": 1739776229952
        }
    ],
    "a": 2049
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., openOrders.
└ accountId integer Account ID. Required unless using the authenticated account.
└ instrumentId string Instrument ID, e.g., ETH-PC-1567.
└ startId integer (Optional) starting order ID in the query.
└ limit integer (Optional) Maximum number of orders to return.

Response Body

Name Type Description
q string Query type, e.g., openOrders.
s string Instrument ID of the queried market, e.g., ETH-PC-1567.
a integer Account ID, e.g., 1234.
P array Array of order objects.
└ o integer Order ID, e.g., 1234.
└ c string Client Order ID, e.g., 43f4159e.
└ a integer Account ID.
└ C integer User ID who created this order.
└ t integer Order Type.
└ i string Instrument ID.
└ m integer Market Id.
└ p string Order price.
└ q string Order total quantity.
└ F string Order filled quantity .
└ fp string Order filled price * quantity.
└ f fee Order fee.
└ s boolean Order side.
└ P boolean Flag for post-only order.
└ S integer Order Status.
└ d integer Timestamp of order creation time.
└ u integer Timestamp of last update time.
Notes

Account Positions Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "accountPositions",
            "marketType": "inclusionPreconf",
            "accountId": 1234
        }
    ]
}

Example Response

{
    "q": "accountPositions",
    "a": 2049,
    "P": [
        {
            "a": 2049,
            "s": 403776,
            "m": 1,
            "q": "0",
            "l": "0",
            "p": "0",
            "e": false,
            "b": false,
            "c": 1742289507000,
            "u": 1742289508000,
            "A": "0"
        },
        {
            "a": 2049,
            "s": 403780,
            "m": 1,
            "q": "0",
            "l": "0",
            "p": "0",
            "e": false,
            "b": false,
            "c": 1742289507000,
            "u": 1742289508000,
            "A": "0"
        }
    ]
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., accountPositions.
└ marketType string Market type, e.g., inclusionPreconf.
└ accountId integer Account ID, e.g., 1234.

Response Body

Name Type Description
q string Query type, e.g., accountPositions.
a integer Account ID of the queried positions.
P array Payload data containing position information.
└ a integer Account Id.
└ s integer Slot number of the position.
└ m integer Market type of the position.
└ q string Position's total quantity.
└ l string Position's locked quantity
└ p string Position purchased price.
└ e boolean Expired flag.
└ b boolean Builder fill enable flag.
└ c integer Position create timestamp.
└ u integer Position last updated timestamp.
└ A integer Position's available quantity.

Preconf Bundles Query

Example Request

{
    "op": "query",
    "args": [
        {
            "queryType": "preconfBundles",
            "slot": 123456
        }
    ]
}

Example Response

{
    "q": "preconfBundles",
    "P": {
        "s": 194265,
        "bu": [
            {
                "u": "c439371a-7095-4de6-82ce-6bf4fc6fd693",
                "txs": [
                    {
                        "r": false,
                        "tx": "0x02f88a827e7e82088b808477359400830334509412643b525cc34282ba84298d32bf2d094448f1c4843b9aca009b45746847617320496e636c7573696f6e20507265636f6e66732e20c080a03b39cc9c4a92f32f8d4bc88546e2655378d4e87468ba74b0d20164ed9c346838a01bdbe85274f17b2c87e4689996089affd2d7d8c542616ef7020f5975bf4ddb52",
                        "h": "0xeb1bca2f601eb124563286455544cc87a1b04b28bd5bed6fb28be81417c4a0de"
                    }
                ],
                "p": "0.00000000013"
            }
        ]
    }
}

Request

Name Type Description
op string e.g. query
args object Arguments
└ queryType string Query type, e.g., preconfBundles.
└ slot integer Slot, e.g., 1234. Optional. Use next slot if not specified.

Response Body

Name Type Description
q string Query type, e.g., preconfBundles.
P array Payload data containing block builder information.
└ s integer Slot ID.
└ bu array Array of preconf bundles in the slot.
└└ u string UUID of the bundle.
└└ p string Gas price of the bundle.
└└ txs array Array of transaction in the bundle
└└└ r boolean Whether this ethereum tranasaction can be reverted.
└└└ tx string Raw ethereum transaction data in the bundle
└└└ h string Transaction hash of transaction data

LOOKUP TABLES

Error Codes

A failed request includes the fields below. See HTTP status when the body is not JSON.

Common errors (errorCode 0-7)

errorCode errorMsgKey Meaning
0 success Success
1 error.permissionDeny Permission denied
2 error.account.notExist Account does not exist
3 error.market.notExist Market does not exist
4 error.market.expired Market expired
5 error.account.inactive Account inactive
6 error.market.tradingDisabled Market trading disabled
7 error.user.locked User account is locked

System errors (errorCode 20-26)

errorCode errorMsgKey Meaning
20 error.system.busy System busy
21 error.system.internal Internal/unknown error
22 error.system.timeout Timeout
23 error.system.validation Validation error
24 error.httpMethod.unsupported Unsupported HTTP method
25 error.contentType.unsupported Unsupported content type
26 error.system.unavailable Service unavailable

Trading errors

Create order (errorCode 50-74)

errorCode errorMsgKey
50 error.price.required
51 error.price.min
52 error.price.max
53 error.price.step
54 error.quantity.required
55 error.quantity.min
56 error.quantity.max
57 error.quantity.step
58 error.clientOrderId.duplicate
59 error.orderLimit
60 error.insufficientFund
61 error.position.insufficient
62 error.collateral.insufficient
63 error.liquidity.insufficient
64 error.clientOrderId.required
65 error.clientOrderId.format
66 error.accountId.required
67 error.orderType.invalid
68 error.orderType.fok.passive
69 error.quantity.nonPositive
70 error.market.required
71 error.price.nonPositive
72 error.side.required
73 error.accountId.notPreconfAccount
74 error.market.botTradingOnly

Cancel order (errorCode 90-96)

errorCode errorMsgKey
90 error.order.notExist
91 error.accountId.required
92 error.instrumentId.required
93 error.orderId.required
94 error.orderId.notBoth
95 error.clientOrderId.invalid
96 error.batchSize.max

Bundle submission (errorCode 190-194)

These message keys use the spelling bundleSumission. Match that string in your client.

errorCode errorMsgKey
190 error.bundleSumission.market.expired
191 error.bundleSumission.preconf.insufficient
192 error.bundleSumission.preconf.max
193 error.bundleSumission.bundle.empty
194 error.bundleSumission.bundle.invalid

Account transfer (errorCode 250-253)

errorCode errorMsgKey
250 error.insufficientFund
251 error.token.unsupported
252 error.fromAccountId.equals.toAccountId
253 error.invalid.accountId

Owner update market (errorCode 430)

errorCode errorMsgKey
430 error.reservedPreconf.position.insufficient

Withdraw (errorCode 310-317)

errorCode errorMsgKey
310 error.quantity.min
311 error.chain.unsupported
312 error.token.unsupported
313 error.insufficientFund
314 error.token.daily.withdraw.capacity.exceeded
315 error.withdraw.requests.empty
316 error.withdraw.requestIds.empty
317 error.withdraw.fee.update.quantity.invalid

API-level errors (errorCode >= 100000)

errorCode errorMsgKey
100000 error.pendingOrDone
100001 error.quantity.nonPositive
100002 error.publicKey.invalid
100003 error.signature.invalid
100004 error.collateralPerSlot.negative
100005 error.builder.notExists
100006 error.validators.max
100007 error.collateralPerSlot.max
100008 error.builders.max
100009 error.slot.invalid
100010 error.login.signature.invalid
100011 error.login.address.invalid
100012 error.login.error.nonce.used
100013 error.login.error.nonce.notExists
100014 error.login.user.notExists
100015 error.login.user.exists
100016 error.login.refreshToken.required
100017 error.login.refreshToken.conflict
100018 error.login.refreshToken.invalid
100019 error.login.session.notFound
100020 error.validator.signature.invalid
100021 error.validator.registered
100022 error.validator.signature.sizeNotMatch
100023 error.validator.signature.max
100024 error.builder.signature.sizeNotMatch
100025 error.builder.signature.max
100026 error.account.id.invalid
100027 error.bundle.rejection.empty
100030 error.ssv.validators.required
100032 error.ssv.validators.invalid
100040 error.ssv.operator.signature.invalid
100041 error.ssv.operator.registered
100042 error.ssv.operator.address.invalid
100043 error.ssv.operator.notRegistered
100044 error.ssv.operator.verification.tx.invalid
100045 error.ssv.operator.verification.tx.notFound
100050 error.obol.validators.required
100052 error.obol.validators.invalid
100060 error.obol.operator.signature.invalid
100061 error.obol.operator.registered
100062 error.obol.operator.address.invalid
100063 error.obol.operator.notRegistered
100064 error.obol.operator.invalid
100070 error.address.invalid
100071 error.timeRange.invalid
100072 error.comment.invalid
100073 error.validator.mode.invalid

Additional request validation codes

errorCode errorMsgKey Meaning
318 error.withdraw.request.invalid Missing or null withdrawal item/required field.
100080 error.builder.delegation.target.required Missing delegation target.
100081 error.builder.delegation.target.conflict Conflicting delegation targets.
100082 error.builder.delegation.entityId.invalid Invalid builder entity identifier.

Markets

Market Status Codes

Status Code Status Description
0 NOT_STARTED Pending to be started
1 ENABLE Market enabled
2 EXPIRED Market expired
3 TRX_SUBMISSION_ENDED Transaction submission time ended
4 FINALIZED Market finalized

Orders

Order Sides

Boolean Side
0 (False) Sell
1 (True) Buy

Order Status Codes

Status Code Status Description
0 STATUS_PENDING Pending (i.e. Not yet sent to market)
1 STATUS_ONBOOK On Book (i.e. Live order in market)
10 STATUS_DONE Done (i.e. Fully executed)
11 STATUS_MANUALLY_CANCELLED Manually cancelled
12 STATUS_AUTO_CANCELLED Auto cancelled
13 STATUS_PARTIALLY_FILLED Partially Filled
14 STATUS_EXPIRED Market expired
99 STATUS_ERROR Error

Order Types

Type Code Meaning
1 Market Order
2 Limit Order
3 Fill-Or-Kill Order

Response Codes

See HTTP status. Check success as well as the HTTP status. Batch endpoints also return a code for each item.

Token IDs

These are the tokens currently supported on Ethgas.

Code Name Token ID Quantity Step Minimum Quantity
ETH ETH 1 0.00001 0.001

Transaction Types

Code Meaning
1 Buy
2 Sell
3 Borrow
4 Lend
5 Interest
6 Transfer In (Between accounts)
7 Transfer Out (Between accounts)
8 External Transfer In (Deposit)
9 External Transfer Out (Withdrawal)
10 Trade
14 Withdrawal Fee
15 Transaction Fee

Market Types

Code Market
1 Inclusion Preconf Market
2 Whole Block Market

Action Types

Action Type returned in some websocket messages.

Type
NewEpoch
MarketExpiry
Snapshot
BlockBuilderChanged
BundleSubmissionDeadline

Builder

Builder Registration Result

Code Reason
0 OK
1 NOT_FOUND
2 SIGNATURE_INVALID
3 ALREADY_REGISTERED