Skip to Content

Usage Reporting

The official JavaScript Hive Client (@graphql-hive/core) collects executed operations and sends them in batches (as a single report, when a buffer is full or every few seconds) over HTTP.

It’s recommended to send a report for more than 1 operation. The maximum payload size is 1 MB.

NameValue
Endpointhttps://app.graphql-hive.com/usage/<ORGANIZATION>/<PROJECT>/<TARGET> or https://app.graphql-hive.com/usage/<TARGET_ID>
Authorization HeaderAuthorization: Bearer <ACCESS_TOKEN>
API version HeaderX-Usage-API-Version: 2
MethodPOST
Content-Type HeaderContent-Type: application/json

You can either use the slug or id of the target for the usage reporting endpoint. Be aware that using the target ID is more resilient in case you rename either your organization, project or target.

For the Authorization header ACCESS_TOKEN value, provide a valid access token with the usage reporting permissions. Learn how to create an access token.

JSON Body structure

TypeScript schema
export interface Report { size: number map: { [k: string]: OperationMapRecord } operations?: RequestOperation[] subscriptionOperations?: SubscriptionOperation[] } export interface OperationMapRecord { operation: string operationName?: string /** * @minItems 1 */ fields: [string, ...string[]] } export interface RequestOperation { timestamp: number operationMapKey: string execution: Execution metadata?: Metadata persistedDocumentHash?: string } export interface Execution { ok: boolean duration: number errorsTotal: number } export interface SubscriptionOperation { timestamp: number operationMapKey: string metadata?: Metadata } export interface Client { name: string version: string } export interface Metadata { client?: Client }
JSON Schema
{ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Report", "additionalProperties": false, "type": "object", "properties": { "size": { "type": "integer" }, "map": { "type": "object", "patternProperties": { "^(.*)$": { "title": "OperationMapRecord", "additionalProperties": false, "type": "object", "properties": { "operation": { "type": "string" }, "operationName": { "type": "string" }, "fields": { "minItems": 1, "type": "array", "items": { "type": "string" } } }, "required": [ "operation", "fields" ] } } }, "operations": { "type": "array", "items": { "title": "RequestOperation", "additionalProperties": false, "type": "object", "properties": { "timestamp": { "type": "integer" }, "operationMapKey": { "type": "string" }, "execution": { "title": "Execution", "additionalProperties": false, "type": "object", "properties": { "ok": { "type": "boolean" }, "duration": { "type": "integer" }, "errorsTotal": { "type": "integer" } }, "required": [ "ok", "duration", "errorsTotal" ] }, "metadata": { "title": "Metadata", "additionalProperties": false, "type": "object", "properties": { "client": { "title": "Client", "additionalProperties": false, "type": "object", "properties": { "name": { "type": "string" }, "version": { "type": "string" } }, "required": [ "name", "version" ] } } }, "persistedDocumentHash": { "type": "string", "title": "PersistedDocumentHash", "pattern": "^[a-zA-Z0-9_-]{1,64}~[a-zA-Z0-9._-]{1,64}~([A-Za-z]|[0-9]|_){1,128}$" } }, "required": [ "timestamp", "operationMapKey", "execution" ] } }, "subscriptionOperations": { "type": "array", "items": { "title": "SubscriptionOperation", "additionalProperties": false, "type": "object", "properties": { "timestamp": { "type": "integer" }, "operationMapKey": { "type": "string" }, "metadata": { "title": "Metadata", "additionalProperties": false, "type": "object", "properties": { "client": { "title": "Client", "additionalProperties": false, "type": "object", "properties": { "name": { "type": "string" }, "version": { "type": "string" } }, "required": [ "name", "version" ] } } } }, "required": [ "timestamp", "operationMapKey" ] } } }, "required": [ "size", "map" ] }

Raw JSON Example Payload

{ "size": 3, "map": { "c3b6d9b0": { "operationName": "me", "operation": "query me { me { id name } }", "fields": ["Query", "Query.me", "User", "User.id", "User.name"] }, "762a45e3": { "operationName": "users", "operation": "query users { users { id } }", "fields": ["Query", "Query.users", "User", "User.id"] }, "12f3712a": { "operationName": "liveCoordinates", "operation": "subscription liveCoordinates { location { x y } }", "fields": [ "Subscription", "Subscription.location", "User", "Location", "Location.x", "Location.y" ] } }, "operations": [ { "operationMapKey": "c3b6d9b0", // points to the 'me' query "timestamp": 1663158676535, // must be within retention period of use plan (free/Pro/enterprise) "execution": { "ok": true, "duration": 150000000, // 150ms in nanoseconds "errorsTotal": 0 }, "metadata": { "client": { "name": "demo", "version": "0.0.1" } } }, { "operationMapKey": "c3b6d9b0", // points to the 'me' query "timestamp": 1663158676589, "execution": { "ok": false, // failed operation "duration": 150000000, // 150ms in nanoseconds "errorsTotal": 1 // 1 GraphQL error }, "metadata": { "client": { "name": "demo", "version": "0.0.1" } } }, { "operationMapKey": "762a45e3", // points to the 'users' query "timestamp": 1663158676589, "execution": { "ok": true, "duration": 150000000, // 150ms in nanoseconds "errorsTotal": 0 }, "metadata": { "client": { "name": "demo", "version": "0.0.1" } } } ], "subscriptionOperations": [ { "operationMapKey": "12f3712a", // points to the 'users' query "timestamp": 1663158676589, "metadata": { "client": { "name": "demo", "version": "0.0.1" } } } ] }

curl example request

curl -X POST \ https://app.graphql-hive.com/usage \ -H 'Authorization: Bearer token-here' \ -H 'X-Usage-API-Version: 2' \ -H 'content-type: application/json' \ -d '{ "size": 1, "map": { "aaa": { "operationName": "me", "operation": "query me { me { id } }", "fields": ["Query", "Query.me", "User", "User.id"] } }, "operations": [{ "operationMapKey" : "c3b6d9b0", "timestamp" : 1663158676535, "execution" : { "ok" : true, "duration" : 150000000, "errorsTotal" : 0 }, "metadata" : { "client" : { "name" : "demo" , "version" : "0.0.1" } } } ] }'

Response

Status CodeMeaning
200Usage data was successfully accepted.
400Errors while processing the sent JSON body.
401Invalid X-Usage-API-Version header provided.
429Rate limited due to exceeding usage reporting quota.
500An unexpected error occured.

The endpoint will return a JSON body response body for 200 and 400 status codes.

200 Status Body

Response 200
{ "id": "c6ba1f9c-44c0-40a1-8089-65f7e4de5de5", "operations": { "accepted": 20, "rejected": 0 } }

400 Status Body

A response with status 400 indicates that the report sent within the request body is not valid. The response body will contain a JSON Schema validation errors that can be used to debug the faulty request body.

Response 400
{ "errors": [ { "message": "Expected union value", "path": "/operations", "errors": [ { "message": "Expected valid unix timestamp in milliseconds", "path": "/operations/0/timestamp" }, { "message": "Expected integer to be greater or equal to 0", "path": "/operations/0/execution/duration" }, { "message": "Expected null", "path": "/operations" } ] } ] }
Last updated on