Skip to content

Report Trading Data (v2)

Report trading data for your engaged projects across different exchanges using the v2 schema.

Overview

This endpoint allows you to submit market maker data for your engaged projects using the v2 schema. In addition to the metrics supported by v1, v2 captures top-of-book and basis-point order book depth, the instrument type (spot or perpetual/derivatives), and a submission type.

All metric fields are required

Unlike v1, where most numeric fields are optional and default to 0, every metric field is required in v2. The quote coin fields are conditional: provide at least one of quoteCoinId or quoteCoinSymbol; if both are sent, quoteCoinId takes precedence and quoteCoinSymbol is ignored.

Endpoint: POST https://data.api.forgd.com/api/v2/report

Authentication: Required (API Key) (docs)

POST Request

Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key for authentication
Check Authentication for more details
x-dry-runbooleanNoRun validation without uploading data
Check Dry Run Mode for more details

Request Body

Request Body Type

ts
type RequestBody = {
  data: {
    date: string // YYYY-MM-DD format
    exchangeId: string // CoinGecko exchange ID
    baseCoinId: string // CoinGecko project ID
    quoteCoinId?: string // CoinGecko quote coin ID
    quoteCoinSymbol?: string // Quote coin symbol (USD, EUR, etc.)
    bidDepth50: number // Bid depth at 50 ticks
    askDepth50: number // Ask depth at 50 ticks
    bidAskDepth50: number // Total depth at 50 ticks
    bidDepth100: number // Bid depth at 100 ticks
    askDepth100: number // Ask depth at 100 ticks
    bidAskDepth100: number // Total depth at 100 ticks
    bidDepth200: number // Bid depth at 200 ticks
    askDepth200: number // Ask depth at 200 ticks
    bidAskDepth200: number // Total depth at 200 ticks
    bidAskSpread: number // Bid-ask spread percentage, ie. 0.5% should be reported as 0.5 (not 0.005)
    orderFillVolumeMaker: number // Maker order fill volume
    orderFillVolumeTaker: number // Taker order fill volume
    instrumentType: 'spot' | 'perp' // Spot market or perpetual/derivatives market
    type: 'project' | 'exchange' | 'prop' // Submission type
    topOfBookPercentage: number // Percentage of instances at top of book (0-100)
    bidDepthTob: number // Bid depth at top of book
    bidDepth10: number // Bid depth at 10 basis points
    bidDepth25: number // Bid depth at 25 basis points
    askDepthTob: number // Ask depth at top of book
    askDepth10: number // Ask depth at 10 basis points
    askDepth25: number // Ask depth at 25 basis points
    orderFillVolumeMakerTob: number // Maker order fill volume executed from top of book
  }[]
}
json
{
  "data": [
    {
      "date": "2024-03-14",
      "exchangeId": "binance",
      "baseCoinId": "solana",
      "quoteCoinId": "tether",
      "bidDepth50": 809,
      "askDepth50": 971,
      "bidAskDepth50": 1780,
      "bidDepth100": 1380,
      "askDepth100": 1520,
      "bidAskDepth100": 2900,
      "bidDepth200": 2180,
      "askDepth200": 2320,
      "bidAskDepth200": 4500,
      "bidAskSpread": 0.1,
      "orderFillVolumeMaker": 8902,
      "orderFillVolumeTaker": 23479,
      "instrumentType": "spot",
      "type": "project",
      "topOfBookPercentage": 42.5,
      "bidDepthTob": 20000,
      "bidDepth10": 45000,
      "bidDepth25": 75000,
      "askDepthTob": 21000,
      "askDepth10": 43000,
      "askDepth25": 71000,
      "orderFillVolumeMakerTob": 125000
    },
    {
      "date": "2024-03-14",
      "exchangeId": "binance",
      "baseCoinId": "solana",
      "quoteCoinSymbol": "EUR",
      "bidDepth50": 456,
      "askDepth50": 523,
      "bidAskDepth50": 979,
      "bidDepth100": 789,
      "askDepth100": 856,
      "bidAskDepth100": 1645,
      "bidDepth200": 1245,
      "askDepth200": 1321,
      "bidAskDepth200": 2566,
      "bidAskSpread": 0.15,
      "orderFillVolumeMaker": 5432,
      "orderFillVolumeTaker": 15678,
      "instrumentType": "spot",
      "type": "project",
      "topOfBookPercentage": 38,
      "bidDepthTob": 12000,
      "bidDepth10": 26000,
      "bidDepth25": 41000,
      "askDepthTob": 12500,
      "askDepth10": 25000,
      "askDepth25": 39000,
      "orderFillVolumeMakerTob": 64000
    }
  ]
}

A single request accepts between 1 and 300 records in the data array.

Request Body Fields

FieldTypeRequiredDescription
datestringrequiredTrading date in YYYY-MM-DD format
exchangeIdstringrequiredExchange ID from list of available exchanges
Available also on exchanges endpoint
baseCoinIdstringrequiredBase coin ID from projects endpoint
quoteCoinIdstringconditionalQuote coin id from list of available coins
Required for trading pairs against crypto currencies where quoteCoinSymbol is not provided - when to use
quoteCoinSymbolstringconditionalQuote coin symbol (USD, EUR, etc.) from list of available currencies
Required for trading pairs against fiat currencies where quoteCoinId is not provided - when to use
bidDepth50numberrequiredBid depth at 50 ticks (in USD)
askDepth50numberrequiredAsk depth at 50 ticks (in USD)
bidAskDepth50numberrequiredTotal depth at 50 ticks (in USD)
Prefer providing bidDepth50 and askDepth50 individually
bidDepth100numberrequiredBid depth at 100 ticks (in USD)
askDepth100numberrequiredAsk depth at 100 ticks (in USD)
bidAskDepth100numberrequiredTotal depth at 100 ticks (in USD)
Prefer providing bidDepth100 and askDepth100 individually
bidDepth200numberrequiredBid depth at 200 ticks (in USD)
askDepth200numberrequiredAsk depth at 200 ticks (in USD)
bidAskDepth200numberrequiredTotal depth at 200 ticks (in USD)
Prefer providing bidDepth200 and askDepth200 individually
bidAskSpreadnumberrequiredBid-ask spread percentage value (0–100)
ie. spread of 0.5% should be reported as 0.5 (not 0.005)
orderFillVolumeMakernumberrequiredMaker order fill volume (in USD)
orderFillVolumeTakernumberrequiredTaker order fill volume (in USD)
instrumentTypeenumrequiredspot or perp — whether the data is for a spot market or a perpetual/derivatives market
Must match the exchange - instrument type and exchange compatibility
typeenumrequiredSubmission type for this row — one of project, exchange, prop - submission type
topOfBookPercentagenumberrequiredPercentage of instances where the market maker was top of book (0–100)
bidDepthTobnumberrequiredBid depth at top of book (in USD)
bidDepth10numberrequiredBid depth at 10 basis points (in USD)
bidDepth25numberrequiredBid depth at 25 basis points (in USD)
askDepthTobnumberrequiredAsk depth at top of book (in USD)
askDepth10numberrequiredAsk depth at 10 basis points (in USD)
askDepth25numberrequiredAsk depth at 25 basis points (in USD)
orderFillVolumeMakerTobnumberrequiredMaker order fill volume executed from top of book (in USD)

Instrument type and exchange compatibility

Set instrumentType to spot for spot markets and perp for perpetual/derivatives markets. The value must be compatible with the exchange you report against:

  • If you submit spot data for an exchange that does not support spot markets, the request fails with: Exchange '<name>' is not a spot exchange; set instrumentType to 'perp' for perpetual/derivatives data
  • If you submit perp data for an exchange that does not support derivatives, the request fails with: Exchange '<name>' is not a derivatives exchange; set instrumentType to 'spot' for spot data
  • When a matching spot or derivatives venue exists for the same exchange, your report is automatically routed to it.

Use the exchanges endpoint or the list of available exchanges to confirm which markets an exchange supports.

Submission type

Set type to match the kind of engagement the data is reported under:

typeUse it for
projectLoan + Call Option and Retainer + Working Capital
exchangeExchange Engagements
propProp Trading

When to use quoteCoinId and quoteCoinSymbol

Use quoteCoinId for trading pairs against crypto currencies:

  • SOL/USDT (use quoteCoinId: 'tether')
  • SOL/USDC (use quoteCoinId: 'usd-coin')
  • SOL/BTC (use quoteCoinId: 'bitcoin')

Use quoteCoinSymbol for trading pairs against fiat currencies:

  • SOL/USD (use quoteCoinSymbol: 'USD')
  • SOL/EUR (use quoteCoinSymbol: 'EUR')
  • SOL/KRW (use quoteCoinSymbol: 'KRW')

At least one of quoteCoinId or quoteCoinSymbol is required.

These fields are not mutually exclusive. When quoteCoinId is set, it determines the quote coin and quoteCoinSymbol is ignored.

Examples

bash
curl -X POST "https://data.api.forgd.com/api/v2/report" \
  -H "Authorization: <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "data": [
      {
        "date": "2024-03-14",
        "exchangeId": "binance",
        "baseCoinId": "solana",
        "quoteCoinId": "tether",
        "bidDepth50": 809,
        "askDepth50": 971,
        "bidAskDepth50": 1780,
        "bidDepth100": 1380,
        "askDepth100": 1520,
        "bidAskDepth100": 2900,
        "bidDepth200": 2180,
        "askDepth200": 2320,
        "bidAskDepth200": 4500,
        "bidAskSpread": 0.1,
        "orderFillVolumeMaker": 8902,
        "orderFillVolumeTaker": 23479,
        "instrumentType": "spot",
        "type": "project",
        "topOfBookPercentage": 42.5,
        "bidDepthTob": 20000,
        "bidDepth10": 45000,
        "bidDepth25": 75000,
        "askDepthTob": 21000,
        "askDepth10": 43000,
        "askDepth25": 71000,
        "orderFillVolumeMakerTob": 125000
      }
    ]
  }'
js
const response = await fetch('https://data.api.forgd.com/api/v2/report', {
  method: 'POST',
  headers: {
    Authorization: '<API_KEY>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    data: [
      {
        date: '2024-03-14',
        exchangeId: 'binance',
        baseCoinId: 'solana',
        quoteCoinId: 'tether',
        bidDepth50: 809,
        askDepth50: 971,
        bidAskDepth50: 1780,
        bidDepth100: 1380,
        askDepth100: 1520,
        bidAskDepth100: 2900,
        bidDepth200: 2180,
        askDepth200: 2320,
        bidAskDepth200: 4500,
        bidAskSpread: 0.1,
        orderFillVolumeMaker: 8902,
        orderFillVolumeTaker: 23479,
        instrumentType: 'spot',
        type: 'project',
        topOfBookPercentage: 42.5,
        bidDepthTob: 20000,
        bidDepth10: 45000,
        bidDepth25: 75000,
        askDepthTob: 21000,
        askDepth10: 43000,
        askDepth25: 71000,
        orderFillVolumeMakerTob: 125000,
      },
    ],
  }),
})

const data = await response.json()

if (response.ok) {
  console.log('Report:', data)
} else {
  console.error('Error:', response.status, response.statusText, data)
}
python
import requests

data = {
    "data": [
        {
            "date": "2024-03-14",
            "exchangeId": "binance",
            "baseCoinId": "solana",
            "quoteCoinId": "tether",
            "bidDepth50": 809,
            "askDepth50": 971,
            "bidAskDepth50": 1780,
            "bidDepth100": 1380,
            "askDepth100": 1520,
            "bidAskDepth100": 2900,
            "bidDepth200": 2180,
            "askDepth200": 2320,
            "bidAskDepth200": 4500,
            "bidAskSpread": 0.1,
            "orderFillVolumeMaker": 8902,
            "orderFillVolumeTaker": 23479,
            "instrumentType": "spot",
            "type": "project",
            "topOfBookPercentage": 42.5,
            "bidDepthTob": 20000,
            "bidDepth10": 45000,
            "bidDepth25": 75000,
            "askDepthTob": 21000,
            "askDepth10": 43000,
            "askDepth25": 71000,
            "orderFillVolumeMakerTob": 125000
        }
    ]
}

response = requests.post(
    'https://data.api.forgd.com/api/v2/report',
    headers={'Authorization': '<API_KEY>'},
    json=data
)

data = response.json()

if response.ok:
    print('Report:', data)
else:
    print('Error:', response.status_code, response.reason, data)

Success Response

HTTP 201 Created

Returns information about the uploaded data including counts of created and updated records.

Response Type

ts
type SuccessResponseType = {
  createdCount: number
  updatedCount: number
}
json
{
  "createdCount": 258,
  "updatedCount": 42
}

Error Responses

HTTP 400 Bad Request

There was an error in the request body. Please check the message field for more details, fix the errors and try again.

ts
type ErrorResponseType = {
  message: {
    path?: string
    message: string
  }[]
  error: string
  statusCode: number
}
json
{
  "message": [
    {
      "path": "data.0.topOfBookPercentage",
      "message": "Required"
    },
    {
      "path": "data.0.instrumentType",
      "message": "Exchange 'Binance' is not a spot exchange; set instrumentType to 'perp' for perpetual/derivatives data"
    },
    {
      "path": "data.5.bidDepth100",
      "message": "Expected number, received string"
    }
  ],
  "error": "Bad Request",
  "statusCode": 400
}

HTTP 401 Unauthorized

The request could not be authenticated. Possible reasons:

ts
type ErrorResponseType = {
  message: string
  statusCode: number
}
json
{
  "message": "Unauthorized",
  "statusCode": 401
}

HTTP 5xx Internal Server Error

The request has failed due to an error on the server side. Most likely there is an internal issue with our server or network - please try again after couple of minutes.

We are getting notified about every 5XX response internally but if this is an recurring issue, please contact us at support@forgd.com.

Dry Run Mode

You can test your data format without actually uploading by setting the x-dry-run header to true. This will validate your data and return the same response format without persisting the data.

js
const response = await fetch('https://data.api.forgd.com/api/v2/report', {
  method: 'POST',
  headers: {
    Authorization: '<API_KEY>',
    'Content-Type': 'application/json',
    'x-dry-run': 'true',
  },
  body: JSON.stringify({
    data: [...],
  }),
})
python
import requests

response = requests.post(
    'https://data.api.forgd.com/api/v2/report',
    headers={
        'Authorization': '<API_KEY>',
        'x-dry-run': 'true'
    },
    json={'data': [...]},
)
bash
curl -X POST "https://data.api.forgd.com/api/v2/report" \
  -H "Authorization: <API_KEY>" \
  -H "Content-Type: application/json" \
  -H "x-dry-run: true" \
  -d '{"data": [...]}'

FAQ & Troubleshooting

Updating existing report data

To update the data, submit the report using this endpoint for the same date, exchangeId, baseCoinId, quote coin (quoteCoinId or quoteCoinSymbol) and instrumentType. Response will contain the counts of created and updated records.

Deleting existing report data

Currently there is no way to delete the report data.

My bid-ask spread in the application is lower than the value I have reported

Common mistake is that the bid-ask spread is reported as a decimal value where 0.5% spread is reported as 0.0005 while it should be reported as 0.5. Please check the your integration and make sure you are reporting the value correctly.

To fix the issue, please submit your past reports again with the correct values and your data will be updated.