DocsAPI reference

API reference

Errors and limits

2 min readReviewed July 2026

GraphJSON uses HTTP status codes plus a JSON or text response body. Handle the status first; error body wording can evolve.

Status codes#

Status Meaning Recommended action
2xx Request succeeded Continue
400 Invalid method, key, payload, timestamp, range, filter, or query Fix the request; do not retry unchanged
429 Ingestion requests are arriving too quickly Retry with exponential backoff and jitter
500 Internal ingestion failure Retry a bounded number of times

Some data and visualization failures are surfaced as 400 even when the underlying message is not a field-level validation error. Record the redacted body for diagnosis.

Error bodies#

Most validation errors look like:

{
  "error": "Invalid API KEY"
}

Rate limiting can return plain text:

Too Many Requests

Use a parser that tolerates both:

async function graphJSONRequest(url, payload) {
  const response = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload),
    signal: AbortSignal.timeout(10_000)
  });

  const text = await response.text();
  let body;

  try {
    body = text ? JSON.parse(text) : null;
  } catch {
    body = text;
  }

  if (!response.ok) {
    const message =
      typeof body === "object" && body?.error ? body.error : String(body);
    throw new Error(`GraphJSON ${response.status}: ${message}`);
  }

  return body;
}

Ingestion limits#

Limit Value
Event payload 10,000 serialized characters
Single logging request 1 event
Bulk logging request 50 events
Ingestion requests 40 per second per workspace
Timestamp Whole Unix seconds

In bulk requests, jsons and timestamps must be non-empty arrays of equal length.

Query limits#

SQL query results are wrapped with an outer limit of 2,000 rows. Mutation statements are blocked.

Read traffic is expected to remain proportionate to stored event volume. GraphJSON may throttle sustained, unusually high rates of unique read queries. Embedded charts use caching, so repeated views of the same configuration are much less expensive than many unique configurations.

For capacity planning beyond ordinary interactive analytics, contact hi@graphjson.com.

Retry policy#

Retry:

  • network failures
  • timeouts
  • 429
  • 500

Do not automatically retry an unchanged 400.

A bounded exponential schedule:

attempt 1: 250–500 ms
attempt 2: 500–1,000 ms
attempt 3: 1–2 s
attempt 4: 2–4 s

Add random jitter, respect an overall deadline, and cap the number of attempts.

Delivery semantics#

Logging endpoints do not expose an idempotency-key mechanism. A network failure can leave the client unsure whether an event was accepted.

For events that must be reconciled:

  1. include a stable source event_id
  2. retain failed jobs in a queue
  3. allow safe redelivery
  4. deduplicate by event_id in SQL

This gives you explicit at-least-once behavior without pretending the transport guarantees exactly once.

Logging safely#

Record:

  • endpoint name
  • status
  • request duration
  • collection
  • application-level event ID
  • redacted error body

Do not record:

  • API key
  • full embed URLs
  • complete customer payloads
  • secrets contained in provider events

Support checklist#

When contacting support, include the approximate time and time zone, endpoint, collection, status, and redacted body. Never include the API key.

Need a hand?

Tell us what you’re building and we’ll point you in the right direction.

Contact support