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.
Name | Value |
---|---|
Endpoint | https://app.graphql-hive.com/usage/<ORGANIZATION>/<PROJECT>/<TARGET> or https://app.graphql-hive.com/usage/<TARGET_ID> |
Authorization Header | Authorization: Bearer <ACCESS_TOKEN> |
API version Header | X-Usage-API-Version: 2 |
Method | POST |
Content-Type Header | Content-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 Code | Meaning |
---|---|
200 | Usage data was successfully accepted. |
400 | Errors while processing the sent JSON body. |
401 | Invalid X-Usage-API-Version header provided. |
429 | Rate limited due to exceeding usage reporting quota. |
500 | An unexpected error occured. |
The endpoint will return a JSON body response body for 200
and 400
status codes.
200 Status Body
{
"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.
{
"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"
}
]
}
]
}