Welcome to the Data Builder Public API. This API allows you to access and query your Perfex CRM data using RESTful endpoints. It's designed to be fast, secure, and developer-friendly.
https://databuilder.polyxgo.com/api/v1/
Getting Started
To use this API, you need a valid Bearer Token. Integration samples are provided for several languages in the sidebar for each endpoint.
• All response data (names, emails, phones, amounts, …) is randomized — no real system data is returned.
• Passwords, payment details, tokens, and secrets are masked or excluded entirely.
• All write operations (POST, PUT, DELETE) are simulated — nothing is persisted to the database.
• To enable sandbox requests, create a token at Admin → Data Builder → API Tokens and set it in Settings → Public Demo Token.
dba_51d5••••••••••••••••••••••••••••••••••••••••d186
Authentication
All API requests must include your API token in the `Authorization` HTTP header as a Bearer token.
Authorization: Bearer YOUR_TOKEN_HERE
HMAC Verification
If your token has HMAC signing enabled, every request must include `X-Timestamp` and `X-Signature` headers to ensure data integrity.
<?php
$method = "POST";
$path = "/api/v1/graphql"; // Always starts with /
$query = ""; // Data after ? in URL
$body = json_encode(["query" => "{ ... }"]);
$timestamp = time();
$secret = "YOUR_HMAC_SECRET";
$bodyHash = hash('sha256', $body);
$canonical = implode("\n", [$method, $path, $query, $bodyHash, $timestamp]);
$signature = hash_hmac('sha256', $canonical, $secret);
// Headers
$headers = [
"Authorization: Bearer YOUR_TOKEN",
"X-Timestamp: " . $timestamp,
"X-Signature: " . $signature,
"Content-Type: application/json"
];
const crypto = require('crypto');
const timestamp = Math.floor(Date.now() / 1000).toString();
const method = "POST";
const path = "/api/v1/graphql";
const query = "";
const body = JSON.stringify({ query: "{ ... }" });
const secret = "YOUR_HMAC_SECRET";
const bodyHash = crypto.createHash('sha256').update(body).digest('hex');
const canonical = [method, path, query, bodyHash, timestamp].join("\n");
const signature = crypto.createHmac('sha256', secret).update(canonical).digest('hex');
const headers = {
"Authorization": "Bearer YOUR_TOKEN",
"X-Timestamp": timestamp,
"X-Signature": signature,
"Content-Type": "application/json"
};
import hmac, hashlib, time, json
timestamp = str(int(time.time()))
method = "POST"
path = "/api/v1/graphql"
query = ""
body = json.dumps({"query": "{ ... }"})
secret = b"YOUR_HMAC_SECRET" # Must be bytes
body_hash = hashlib.sha256(body.encode()).hexdigest()
canonical = "\n".join([method, path, query, body_hash, timestamp])
signature = hmac.new(secret, canonical.encode(), hashlib.sha256).hexdigest()
headers = {
"Authorization": "Bearer YOUR_TOKEN",
"X-Timestamp": timestamp,
"X-Signature": signature,
"Content-Type": "application/json"
}
# Example: Manual test with pre-calculated values
# Replace timestamps/signatures with values from your local calculator
curl -X POST 'https://your-domain.com/api/v1/graphql' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'X-Timestamp: 1711900000' \
-H 'X-Signature: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' \
-H 'Content-Type: application/json' \
-d '{"query": "{ ... }"}'
The signature is computed over a strictly ordered string to ensure both client and server validate the exact same data context:
{METHOD}\n{PATH}\n{QUERY}\n{SHA256_BODY}\n{TIMESTAMP}
- \n: Represents a literal newline character (LF).
- {PATH}: Must begin with a leading slash (e.g.
/api/v1/graphql). - {SHA256_BODY}: A lowercase hex-encoded SHA256 hash of the raw request body.
Testing with Postman
Complete guide to export, import, and configure the API collection in Postman for testing all REST and GraphQL endpoints.
Step 1 — Create an API Token
Before you can make any API request, you need a valid API token.
- Go to Admin → Data Builder → API Tokens
- Click "Create Token"
- Fill in the token name (e.g.,
Postman Testing) - Select Scopes: choose
tables,views, andwriteas needed - Select Allowed Tables and Allowed Views the token can access
- Click Save
- Copy the token immediately — it is only shown once
dba_{48_hex_characters}.
Step 2 — Export the Postman Collection
Download the pre-built collection with all endpoints, headers, and query parameters.
Step 3 — Import into Postman
Import the downloaded JSON file into your Postman workspace.
- Open Postman (desktop app or web)
- Click Import (top-left, or
Ctrl+O/⌘+O) - Drag and drop the
.jsonfile or click "Upload Files" - Click "Import" to confirm
- The collection "Data Builder API" appears in your sidebar with all folders:
Resources,Reports,GraphQL
Step 4 — Configure Collection Variables
The exported collection uses two variables that you must set before testing.
| Variable | Value | Description |
|---|---|---|
{{baseUrl}} |
https://databuilder.polyxgo.com/api/v1 |
API base URL — auto-filled from export, update if your domain changes |
{{api_token}} |
dba_xxxxxxx... |
Paste the token you created in Step 1 |
{{hmac_secret}} |
Optional secret |
The HMAC Secret key (only if HMAC is enabled for the token) |
- Click the collection name "Data Builder API" in the sidebar
- Go to the "Variables" tab
baseUrlis pre-filled — update the CURRENT VALUE column if your server URL differs (e.g.,https://yourdomain.com/api/v1)- Set
api_tokenCURRENT VALUE to your token from Step 1 - Click Save (
Ctrl+S/⌘+S)
Bearer {{api_token}}. All requests inherit this automatically — no need to set Authorization on each request individually.
Step 5 — Send Your First Request
You're all set! Try a quick test:
- Expand Resources folder in the collection sidebar
- Click any GET List request
- The URL bar shows:
{{baseUrl}}/resource_name - Click the Send button
- View the JSON response in the Body tab below ✓
Step 6 — Production Security: HMAC Signatures
If your token has an HMAC Secret configured, Postman must generate a valid X-Signature for every request. You can automate this using a Pre-request Script:
const timestamp = Math.floor(Date.now() / 1000).toString();
const method = pm.request.method.toUpperCase();
const secret = pm.environment.get("hmac_secret");
if (secret) {
const url = pm.request.url;
// Build path: ensure it starts with /
const path = "/" + url.getPathWithQuery().split('?')[0];
const query = url.getQueryString() || "";
// Body digest (SHA256)
const bodyRaw = pm.request.body.raw || "";
const bodyHash = CryptoJS.SHA256(bodyRaw).toString();
// Canonical string: METHOD\nPATH\nQUERY\nBODY_HASH\nTIMESTAMP
const canonical = [method, path, query, bodyHash, timestamp].join("\n");
const signature = CryptoJS.HmacSHA256(canonical, secret).toString();
pm.request.headers.add({ key: 'X-Timestamp', value: timestamp });
pm.request.headers.add({ key: 'X-Signature', value: signature });
}
Paste this script into the "Pre-request Script" tab of the collection (or a specific request) and ensure the {{hmac_secret}} variable is set.
Available Query Parameters
List endpoints include pre-configured query parameters (disabled by default). Enable them in the Params tab:
| Param | Example | Description |
|---|---|---|
page |
1 |
Page number |
per_page |
25 |
Records per page (max 1000) |
sort |
-id |
Sort field — prefix - for DESC |
fields |
id,name,email |
Sparse fieldset — only return listed columns |
filter |
status:1 |
Filter results by field value |
Testing with OpenAPI
Use the exported OpenAPI 3.0 specification to test your REST & GraphQL endpoints in Swagger UI, Insomnia, or integrate with AI platforms like ChatGPT (OpenAI Actions).
Step 1 — Download the OpenAPI Spec
Export the auto-generated OpenAPI 3.0.3 YAML file that includes all your REST and GraphQL endpoints.
Custom YAML Export
0Select the tables you want to include in the OpenAPI 3.1.0 YAML spec for use with ChatGPT / OpenAI Actions.
Step 2 — Import into Your Favorite Tool
The OpenAPI spec can be used with many tools:
- Open editor.swagger.io
- Go to File → Import File
- Upload the
.yamlfile - Click Authorize and enter your token
- Click Try it out on any endpoint
- Open Insomnia and create a new project
- Click Import → select the
.yamlfile - Set Bearer Token in environment
- All endpoints appear with parameters pre-filled
- Click Send to test
Step 3 — Integrate with ChatGPT (OpenAI Actions)
Use the OpenAPI spec to create a Custom GPT Action that allows ChatGPT to query your CRM data in real-time.
- Go to ChatGPT GPT Editor → Create a GPT
- In the Configure tab, scroll down to Actions → click "Create new action"
- Click "Import from URL" or paste the raw YAML content into the schema editor
- Set Authentication: select
API Key, Auth Type:Bearer, paste your API token - Click "Save" — ChatGPT can now query your API endpoints
With the right API branches configured, your Custom GPT becomes a powerful AI-powered CRM analyst. Here are some practical scenarios:
Step 4 — Testing GraphQL with the OpenAPI Spec
The OpenAPI export includes the POST /graphql endpoint schema. Here's how to use it:
# In Swagger UI's "Try it out" for POST /graphql:
# Set the request body to:
{
"query": "{ staffs(limit: 5) { id email firstname lastname } }",
"variables": {},
"operationName": null
}
# For mutations:
{
"query": "mutation { createProject(input: { name: \"New Project\", clientid: 1 }) { id name } }",
"variables": {}
}
# List query
curl -X POST 'https://databuilder.polyxgo.com/api/v1/graphql' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"query": "{ staffs(limit: 5) { id email firstname lastname } }"
}'
# Introspection query (discover all types)
curl -X POST 'https://databuilder.polyxgo.com/api/v1/graphql' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"query": "{ __schema { types { name kind } } }"
}'
# Mutation example
curl -X POST 'https://databuilder.polyxgo.com/api/v1/graphql' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"query": "mutation { createProject(input: { name: \\"API Test\\", clientid: 1 }) { id name } }"
}'
# Example prompts you can use with your Custom GPT:
"List all staff members with their email addresses"
→ GPT will call: POST /graphql with query { staffs { id firstname lastname email } }
"Show me the 5 latest projects"
→ GPT will call: GET /projects?sort=-id&per_page=5
"Create a new task for project ID 3 with name 'Review API docs'"
→ GPT will call: POST /tasks with body { rel_type: "project", rel_id: 3, name: "Review API docs" }
"Get the schema of the invoices table"
→ GPT will call: GET /invoices/schema
"Run a monthly revenue report grouped by status"
→ GPT will call: GET /reports/invoices/aggregate?dimension=status&measure=total&aggregation=sum&period=monthly
What's Included in the Spec
| Feature | Details |
|---|---|
| REST CRUD | GET list, GET by ID, POST create, PUT update, DELETE, GET schema — for every allowed table |
| Reports | Query and Aggregate endpoints for every published View/Report |
| GraphQL | POST /graphql with query, variables, and operationName schema |
| Authentication | Bearer Token (BearerAuth) security scheme |
| Query Params | page, per_page, sort, fields, filter — described with types and defaults |
| Error Schema | RFC 9457 Problem Details schema for 401, 403, 429 responses |
- The spec is dynamically generated based on your current allowed tables and views — export again after changes.
- For ChatGPT Actions, keep your token scopes minimal (read-only) for safety.
- Use the Postman Collection for more detailed request body samples and pre-configured queries.
- If HMAC is enabled on your token, see the Authentication section for signing details.
Deployment Guide
Server-level configuration for production deployments. Some security features require web server configuration — PHP cannot intercept slow HTTP attacks because they occur before PHP receives the request.
Slow HTTP Protection
Protects against Slowloris and similar slow-read/slow-header attacks.
Apache
Add to your VirtualHost or .htaccess. Requires mod_reqtimeout (enabled by default on most Apache installs).
# Protects against slow-read and slow-header attacks (Slowloris, etc.)
RequestReadTimeout header=20-40,MinRate=500 body=30,MinRate=500header=20-40,MinRate=500 — 20s to start headers, 40s max; min 500 B/s transfer ratebody=30,MinRate=500 — 30s total body read time; min 500 B/s
Nginx
Add to your server {} or location /api/ {} block.
# Slow HTTP protection
client_header_timeout 10s;
client_body_timeout 10s;
client_max_body_size 256k; # Matches application DDoS shield body limit
keepalive_timeout 30s;
send_timeout 10s;Body Size Limit Alignment
The application DDoS shield middleware enforces a configurable body size limit (default 256KB). Align your web server limit to match — if the web server limit is higher, it wastes resources receiving oversized payloads before the application check rejects them.
| Server | Directive |
|---|---|
| Apache | LimitRequestBody 262144 |
| Nginx | client_max_body_size 256k |
MySQL Permissions
The tbldata_builder_api_rate table contains rate counters that must only be writable by the application DB user. Restricting access prevents unauthorized counter manipulation.
-- Revoke from any monitoring/reporting users
REVOKE SELECT, INSERT, UPDATE, DELETE
ON your_db.tbldata_builder_api_rate FROM 'readonly_user'@'%';
-- Grant only to the application user
GRANT SELECT, INSERT, UPDATE, DELETE
ON your_db.tbldata_builder_api_rate TO 'app_user'@'localhost';tbldata_builder_api_logs contains sensitive audit data — also restrict to app user and admin only.
Reverse Proxy / WAF
The application-level DDoS shield handles body size limits (413), IP-level fixed-window throttling, and malformed payload detection. For volumetric DDoS (layer 3/4) or large-scale layer 7 attacks, use external solutions:
Cloudflare Rate Limiting Rule (example)
Match: http.request.uri.path contains "/api/v1/"
Action: Rate limiting — 500 requests per minute per IP
Response: 429 Too Many RequestsHTTPS Enforcement
All API tokens sent via Authorization: Bearer header must be transmitted over HTTPS only.
Apache
# Enforce HTTPS for API routes
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/api/v1/
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]Nginx
if ($scheme != "https") {
return 301 https://$host$request_uri;
}Production Checklist
Ensure all items are configured before going live.
client_max_body_size matches application body limit (default 256KB)
api_rate and api_logs tables restricted to app user
/api/v1/ routes
api_allow_query_token left OFF (default) unless embed mode intentionally needed
Public Chart Reports
Public data views with embeddable chart reports. Click any report to open it in a new tab.
/embed/report/collection-efficiency-by-invoice
/embed/report/project-progress-overview
/embed/report/project-time-billable-report
/embed/report/staff-billable-time-report
Error Reference
All API error responses follow RFC 9457 Problem Details. Each error includes a type URI linking to this reference. Click any error slug for details.
query-string-too-long
The URL query string exceeds the maximum allowed length (default 4KB). This is a protection against…
DdosShieldMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-query-string-too-long |
| Description | The URL query string exceeds the maximum allowed length (default 4KB). This is a protection against query-based abuse. |
| Resolution | Reduce the number or length of query parameters. Use POST with a JSON body for complex queries. |
| Source | DdosShieldMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-query-string-too-long",
"title": "Query String Too Long",
"status": 400,
"detail": "The URL query string exceeds the maximum allowed length (default 4KB). This is a protection against query-based abuse.",
"instance": "/api/v1/example"
}
empty-body
The request body is empty or contains only whitespace. GraphQL requests require a JSON body with at…
Db_graphql
| Type URI | https://databuilder.polyxgo.com/api_docs#error-empty-body |
| Description | The request body is empty or contains only whitespace. GraphQL requests require a JSON body with at least a `query` field. |
| Resolution | Send a JSON body: `{"query": "{ _ping }", "variables": null}`. |
| Source | Db_graphql |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-empty-body",
"title": "Empty Body",
"status": 400,
"detail": "The request body is empty or contains only whitespace. GraphQL requests require a JSON body with at least a `query` field.",
"instance": "/api/v1/example"
}
batching-not-supported
GraphQL operation batching (sending an array of operations in a single request) is not supported. T…
Db_graphql
| Type URI | https://databuilder.polyxgo.com/api_docs#error-batching-not-supported |
| Description | GraphQL operation batching (sending an array of operations in a single request) is not supported. This restriction prevents rate-limit bypass via operation packing. |
| Resolution | Send a single GraphQL operation object per request, not an array. |
| Source | Db_graphql |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-batching-not-supported",
"title": "Batching Not Supported",
"status": 400,
"detail": "GraphQL operation batching (sending an array of operations in a single request) is not supported. This restriction prevents rate-limit bypass via operation packing.",
"instance": "/api/v1/example"
}
invalid-request
The request body is not a valid JSON object or is missing required fields. GraphQL requests must co…
Db_graphql
| Type URI | https://databuilder.polyxgo.com/api_docs#error-invalid-request |
| Description | The request body is not a valid JSON object or is missing required fields. GraphQL requests must contain at least a `query` field. |
| Resolution | Ensure the request body is a valid JSON object with a `query` field: `{"query": "...", "variables": {}, "operationName": null}`. |
| Source | Db_graphql |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-invalid-request",
"title": "Invalid Request",
"status": 400,
"detail": "The request body is not a valid JSON object or is missing required fields. GraphQL requests must contain at least a `query` field.",
"instance": "/api/v1/example"
}
bad-request
The request body is empty, not valid JSON, or missing required fields for the operation.
Db_resources
| Type URI | https://databuilder.polyxgo.com/api_docs#error-bad-request |
| Description | The request body is empty, not valid JSON, or missing required fields for the operation. |
| Resolution | Send a valid JSON body with the required fields. Use the schema endpoint (`GET /{resource}/schema`) to see available columns. |
| Source | Db_resources |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-bad-request",
"title": "Bad Request",
"status": 400,
"detail": "The request body is empty, not valid JSON, or missing required fields for the operation.",
"instance": "/api/v1/example"
}
invalid-parameter
One or more query parameters have invalid values. For aggregation endpoints, the `aggregation` para…
Db_views
| Type URI | https://databuilder.polyxgo.com/api_docs#error-invalid-parameter |
| Description | One or more query parameters have invalid values. For aggregation endpoints, the `aggregation` parameter must be one of: sum, avg, count, min, max. |
| Resolution | Check the error detail for which parameter is invalid and what values are accepted. |
| Source | Db_views |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-invalid-parameter",
"title": "Invalid Parameter",
"status": 400,
"detail": "One or more query parameters have invalid values. For aggregation endpoints, the `aggregation` parameter must be one of: sum, avg, count, min, max.",
"instance": "/api/v1/example"
}
missing-token
No API token was provided in the request. The API requires authentication via a Bearer token in the…
AuthGateMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-missing-token |
| Description | No API token was provided in the request. The API requires authentication via a Bearer token in the Authorization header, or a query parameter for embed-type tokens. |
| Resolution | Include the token in the Authorization header: `Authorization: Bearer dba_your_token_here`. For embed-type tokens, you may also use `?token=dba_your_token_here`. |
| Source | AuthGateMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-missing-token",
"title": "Missing Token",
"status": 401,
"detail": "No API token was provided in the request. The API requires authentication via a Bearer token in the Authorization header, or a query parameter for embed-type tokens.",
"instance": "/api/v1/example"
}
invalid-token
The provided token is not valid. It may have been revoked, expired, or was never issued. Tokens are…
AuthGateMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-invalid-token |
| Description | The provided token is not valid. It may have been revoked, expired, or was never issued. Tokens are validated by computing SHA-256 hash and comparing against stored hashes. |
| Resolution | Verify the token is correct and has not been revoked. Check if the token has an expiration date. Generate a new token from the admin panel if needed. |
| Source | AuthGateMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-invalid-token",
"title": "Invalid Token",
"status": 401,
"detail": "The provided token is not valid. It may have been revoked, expired, or was never issued. Tokens are validated by computing SHA-256 hash and comparing against stored hashes.",
"instance": "/api/v1/example"
}
query-token-disabled
Tokens passed via query parameter (`?token=...`) are restricted. Only embed-type tokens are allowed…
AuthGateMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-query-token-disabled |
| Description | Tokens passed via query parameter (`?token=...`) are restricted. Only embed-type tokens are allowed in query parameters to prevent token leakage in server logs and browser history. |
| Resolution | Use the Authorization header instead: `Authorization: Bearer dba_your_token_here`. If you need query parameter support, create an embed-type token in the admin panel. |
| Source | AuthGateMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-query-token-disabled",
"title": "Query Token Disabled",
"status": 401,
"detail": "Tokens passed via query parameter (`?token=...`) are restricted. Only embed-type tokens are allowed in query parameters to prevent token leakage in server logs and browser history.",
"instance": "/api/v1/example"
}
invalid-signature
HMAC-SHA256 signature verification failed. The token has an HMAC secret configured, which requires …
AuthGateMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-invalid-signature |
| Description | HMAC-SHA256 signature verification failed. The token has an HMAC secret configured, which requires all requests to include a valid `X-Signature` header. The canonical string is: METHOD\nPATH\nQUERY\nSHA256(body)\nTIMESTAMP. |
| Resolution | Ensure you are computing the HMAC-SHA256 signature correctly using the token's HMAC secret. Include both `X-Signature` and `X-Timestamp` headers. The timestamp must be within ±300 seconds of the server time. |
| Source | AuthGateMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-invalid-signature",
"title": "Invalid Signature",
"status": 401,
"detail": "HMAC-SHA256 signature verification failed. The token has an HMAC secret configured, which requires all requests to include a valid `X-Signature` header. The canonical string is: METHOD\\nPATH\\nQUERY\\nSHA256(body)\\nTIMESTAMP.",
"instance": "/api/v1/example"
}
embed-type-required
Query parameter tokens must be of embed type. Regular tokens cannot be passed via URL to prevent ex…
AuthGateMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-embed-type-required |
| Description | Query parameter tokens must be of embed type. Regular tokens cannot be passed via URL to prevent exposure in server logs, browser history, and referrer headers. |
| Resolution | Create an embed-type token in the admin panel specifically for use in URLs and iframes. Regular tokens must use the Authorization header. |
| Source | AuthGateMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-embed-type-required",
"title": "Embed Type Required",
"status": 403,
"detail": "Query parameter tokens must be of embed type. Regular tokens cannot be passed via URL to prevent exposure in server logs, browser history, and referrer headers.",
"instance": "/api/v1/example"
}
domain-not-allowed
The request Origin header does not match any domain in the token's domain whitelist. This is an app…
AuthGateMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-domain-not-allowed |
| Description | The request Origin header does not match any domain in the token's domain whitelist. This is an application-level policy check (not CORS), enforced after authentication. |
| Resolution | Ensure your request originates from a domain listed in the token's domain whitelist. Contact the API administrator to add your domain, or use a token without domain restrictions. |
| Source | AuthGateMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-domain-not-allowed",
"title": "Domain Not Allowed",
"status": 403,
"detail": "The request Origin header does not match any domain in the token's domain whitelist. This is an application-level policy check (not CORS), enforced after authentication.",
"instance": "/api/v1/example"
}
unauthorized
The token was not properly resolved before the scope verification stage. This typically indicates a…
ScopeVerifierMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-unauthorized |
| Description | The token was not properly resolved before the scope verification stage. This typically indicates a middleware pipeline configuration error. |
| Resolution | This is a server-side configuration issue. Contact the system administrator. |
| Source | ScopeVerifierMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-unauthorized",
"title": "Unauthorized",
"status": 403,
"detail": "The token was not properly resolved before the scope verification stage. This typically indicates a middleware pipeline configuration error.",
"instance": "/api/v1/example"
}
ip-not-allowed
The client IP address is not in the token's IP allowlist. IP filtering supports exact match and IPv…
ScopeVerifierMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-ip-not-allowed |
| Description | The client IP address is not in the token's IP allowlist. IP filtering supports exact match and IPv4 CIDR notation (e.g., 192.168.1.0/24). |
| Resolution | Ensure your request originates from an IP address listed in the token's IP whitelist. Contact the API administrator to update the whitelist. Note: IPv6 addresses are not currently supported for CIDR matching. |
| Source | ScopeVerifierMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-ip-not-allowed",
"title": "IP Not Allowed",
"status": 403,
"detail": "The client IP address is not in the token's IP allowlist. IP filtering supports exact match and IPv4 CIDR notation (e.g., 192.168.1.0/24).",
"instance": "/api/v1/example"
}
scope-not-allowed
The token does not have the required scope for this operation. Scopes control which API features a …
ScopeVerifierMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-scope-not-allowed |
| Description | The token does not have the required scope for this operation. Scopes control which API features a token can access: `tables` (table endpoints), `views` (report endpoints), `graphql` (GraphQL endpoint), `write` (mutations/POST/PUT/DELETE). |
| Resolution | Update the token's scopes in the admin panel to include the required scope. Check which scope is needed from the error detail message. |
| Source | ScopeVerifierMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-scope-not-allowed",
"title": "Scope Not Allowed",
"status": 403,
"detail": "The token does not have the required scope for this operation. Scopes control which API features a token can access: `tables` (table endpoints), `views` (report endpoints), `graphql` (GraphQL endpoint), `write` (mutations/POST/PUT/DELETE).",
"instance": "/api/v1/example"
}
table-not-allowed
The token has a restricted `allowed_tables` list and the requested table is not included. When `all…
ScopeVerifierMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-table-not-allowed |
| Description | The token has a restricted `allowed_tables` list and the requested table is not included. When `allowed_tables` is empty, all whitelisted tables are accessible. |
| Resolution | Add the target table to the token's allowed_tables list in the admin panel, or use a token with unrestricted table access. |
| Source | ScopeVerifierMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-table-not-allowed",
"title": "Table Not Allowed",
"status": 403,
"detail": "The token has a restricted `allowed_tables` list and the requested table is not included. When `allowed_tables` is empty, all whitelisted tables are accessible.",
"instance": "/api/v1/example"
}
view-not-allowed
The token has a restricted `allowed_views` list and the requested view/report is not included. When…
ScopeVerifierMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-view-not-allowed |
| Description | The token has a restricted `allowed_views` list and the requested view/report is not included. When `allowed_views` is empty, all published views are accessible. |
| Resolution | Add the target view to the token's allowed_views list in the admin panel, or use a token with unrestricted view access. |
| Source | ScopeVerifierMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-view-not-allowed",
"title": "View Not Allowed",
"status": 403,
"detail": "The token has a restricted `allowed_views` list and the requested view/report is not included. When `allowed_views` is empty, all published views are accessible.",
"instance": "/api/v1/example"
}
write-not-allowed
The token does not have write permissions. Write operations (POST, PUT, DELETE) require the `write`…
ScopeVerifierMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-write-not-allowed |
| Description | The token does not have write permissions. Write operations (POST, PUT, DELETE) require the `write` scope to be explicitly enabled on the token. |
| Resolution | Enable the `write` scope on your API token in the admin panel. Write access is disabled by default as a security measure. |
| Source | ScopeVerifierMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-write-not-allowed",
"title": "Write Not Allowed",
"status": 403,
"detail": "The token does not have write permissions. Write operations (POST, PUT, DELETE) require the `write` scope to be explicitly enabled on the token.",
"instance": "/api/v1/example"
}
forbidden
The token does not have the `write` scope required for mutative operations (POST, PUT, DELETE).
Db_resources
| Type URI | https://databuilder.polyxgo.com/api_docs#error-forbidden |
| Description | The token does not have the `write` scope required for mutative operations (POST, PUT, DELETE). |
| Resolution | Enable the `allow_write` scope on the API token in the admin panel. |
| Source | Db_resources |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-forbidden",
"title": "Write Not Permitted",
"status": 403,
"detail": "The token does not have the `write` scope required for mutative operations (POST, PUT, DELETE).",
"instance": "/api/v1/example"
}
feature-disabled
The requested feature (e.g., GraphQL API) is not enabled in the system settings. Features can be to…
Db_graphql
| Type URI | https://databuilder.polyxgo.com/api_docs#error-feature-disabled |
| Description | The requested feature (e.g., GraphQL API) is not enabled in the system settings. Features can be toggled by the administrator. |
| Resolution | Contact the API administrator to enable the feature in Setup → Settings → Data Builder → API. |
| Source | Db_graphql |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-feature-disabled",
"title": "Feature Disabled",
"status": 404,
"detail": "The requested feature (e.g., GraphQL API) is not enabled in the system settings. Features can be toggled by the administrator.",
"instance": "/api/v1/example"
}
not-found
The requested resource, record, table, or view was not found. This can mean the entity doesn't exis…
Db_resources / Db_tables / Db_views
| Type URI | https://databuilder.polyxgo.com/api_docs#error-not-found |
| Description | The requested resource, record, table, or view was not found. This can mean the entity doesn't exist, is not published, or is not accessible with the current token permissions. |
| Resolution | Verify the resource name, record ID, or view slug is correct. Check that the resource is whitelisted and the view is published. |
| Source | Db_resources / Db_tables / Db_views |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-not-found",
"title": "Not Found",
"status": 404,
"detail": "The requested resource, record, table, or view was not found. This can mean the entity doesn't exist, is not published, or is not accessible with the current token permissions.",
"instance": "/api/v1/example"
}
method-not-allowed
The HTTP method used is not supported for this endpoint. The GraphQL endpoint only accepts POST. Ta…
Db_graphql / Db_tables / Db_views / Db_resources
| Type URI | https://databuilder.polyxgo.com/api_docs#error-method-not-allowed |
| Description | The HTTP method used is not supported for this endpoint. The GraphQL endpoint only accepts POST. Table and view endpoints only accept GET. Resource endpoints support GET, POST, PUT, DELETE depending on the operation. |
| Resolution | Check the `Allow` response header for the list of supported methods. Use POST for GraphQL queries and GET for read-only endpoints. |
| Source | Db_graphql / Db_tables / Db_views / Db_resources |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-method-not-allowed",
"title": "Method Not Allowed",
"status": 405,
"detail": "The HTTP method used is not supported for this endpoint. The GraphQL endpoint only accepts POST. Table and view endpoints only accept GET. Resource endpoints support GET, POST, PUT, DELETE depending on the operation.",
"instance": "/api/v1/example"
}
payload-too-large
The request body exceeds the maximum allowed size (default 256KB, configurable via admin settings).
DdosShieldMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-payload-too-large |
| Description | The request body exceeds the maximum allowed size (default 256KB, configurable via admin settings). |
| Resolution | Reduce the request body size. For large data imports, use chunked requests or contact the API administrator to increase the limit. |
| Source | DdosShieldMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-payload-too-large",
"title": "Payload Too Large",
"status": 413,
"detail": "The request body exceeds the maximum allowed size (default 256KB, configurable via admin settings).",
"instance": "/api/v1/example"
}
unsupported-media-type
The request Content-Type is not `application/json`. All API requests with a body (POST, PUT, PATCH,…
Db_api_base
| Type URI | https://databuilder.polyxgo.com/api_docs#error-unsupported-media-type |
| Description | The request Content-Type is not `application/json`. All API requests with a body (POST, PUT, PATCH, DELETE) must use JSON encoding. |
| Resolution | Set the Content-Type header to `application/json` and ensure the request body is valid JSON. |
| Source | Db_api_base |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-unsupported-media-type",
"title": "Unsupported Media Type",
"status": 415,
"detail": "The request Content-Type is not `application/json`. All API requests with a body (POST, PUT, PATCH, DELETE) must use JSON encoding.",
"instance": "/api/v1/example"
}
creation-failed
The INSERT operation failed. This usually means required database columns are missing from the requ…
Db_resources
| Type URI | https://databuilder.polyxgo.com/api_docs#error-creation-failed |
| Description | The INSERT operation failed. This usually means required database columns are missing from the request body, or a constraint violation occurred (e.g., unique key, foreign key). |
| Resolution | Check the error detail for specifics. Use the schema endpoint to see required columns. Ensure unique constraints are not violated. |
| Source | Db_resources |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-creation-failed",
"title": "Creation Failed",
"status": 422,
"detail": "The INSERT operation failed. This usually means required database columns are missing from the request body, or a constraint violation occurred (e.g., unique key, foreign key).",
"instance": "/api/v1/example"
}
update-failed
The UPDATE operation failed. The record exists but could not be modified, possibly due to a constra…
Db_resources
| Type URI | https://databuilder.polyxgo.com/api_docs#error-update-failed |
| Description | The UPDATE operation failed. The record exists but could not be modified, possibly due to a constraint violation or invalid field values. |
| Resolution | Check the error detail. Verify the field values are valid for their column types and do not violate constraints. |
| Source | Db_resources |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-update-failed",
"title": "Update Failed",
"status": 422,
"detail": "The UPDATE operation failed. The record exists but could not be modified, possibly due to a constraint violation or invalid field values.",
"instance": "/api/v1/example"
}
deletion-failed
The DELETE operation failed. The record exists but could not be deleted, usually due to foreign key…
Db_resources
| Type URI | https://databuilder.polyxgo.com/api_docs#error-deletion-failed |
| Description | The DELETE operation failed. The record exists but could not be deleted, usually due to foreign key constraints from other tables referencing this record. |
| Resolution | Remove or update dependent records before deleting. Check the database for foreign key relationships. |
| Source | Db_resources |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-deletion-failed",
"title": "Deletion Failed",
"status": 422,
"detail": "The DELETE operation failed. The record exists but could not be deleted, usually due to foreign key constraints from other tables referencing this record.",
"instance": "/api/v1/example"
}
too-many-requests
Rate limit exceeded. This can be triggered by either the global IP throttle (DDoS protection) or th…
DdosShieldMiddleware / RateLimiterMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-too-many-requests |
| Description | Rate limit exceeded. This can be triggered by either the global IP throttle (DDoS protection) or the per-token rate limiter. Check the `Retry-After` and `RateLimit` response headers for timing information. |
| Resolution | Wait for the time indicated in the `Retry-After` header before sending more requests. Implement exponential backoff in your client. To increase limits, request a higher rate_limit value from the API administrator. |
| Source | DdosShieldMiddleware / RateLimiterMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-too-many-requests",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit exceeded. This can be triggered by either the global IP throttle (DDoS protection) or the per-token rate limiter. Check the `Retry-After` and `RateLimit` response headers for timing information.",
"instance": "/api/v1/example"
}
view-execution-error
The saved view query failed to execute. This can happen if the underlying table structure has chang…
Db_views
| Type URI | https://databuilder.polyxgo.com/api_docs#error-view-execution-error |
| Description | The saved view query failed to execute. This can happen if the underlying table structure has changed since the view was created. |
| Resolution | Edit the view in the Data Builder admin panel to update the query configuration. Check that all referenced tables and columns still exist. |
| Source | Db_views |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-view-execution-error",
"title": "View Execution Error",
"status": 500,
"detail": "The saved view query failed to execute. This can happen if the underlying table structure has changed since the view was created.",
"instance": "/api/v1/example"
}
aggregation-error
The aggregation query failed to execute. The dimension or measure field may not exist in the view, …
Db_views
| Type URI | https://databuilder.polyxgo.com/api_docs#error-aggregation-error |
| Description | The aggregation query failed to execute. The dimension or measure field may not exist in the view, or the aggregation function may not be compatible with the column type. |
| Resolution | Verify that the `dimension` and `measure` parameters reference valid field aliases from the view. Use the view schema endpoint to check available fields. |
| Source | Db_views |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-aggregation-error",
"title": "Aggregation Error",
"status": 500,
"detail": "The aggregation query failed to execute. The dimension or measure field may not exist in the view, or the aggregation function may not be compatible with the column type.",
"instance": "/api/v1/example"
}
service-unavailable
The rate limiting backend is temporarily unavailable. The API uses a fail-closed strategy: when the…
DdosShieldMiddleware / RateLimiterMiddleware
| Type URI | https://databuilder.polyxgo.com/api_docs#error-service-unavailable |
| Description | The rate limiting backend is temporarily unavailable. The API uses a fail-closed strategy: when the rate limiter cannot verify your request count, all requests are rejected rather than silently bypassing the limit. |
| Resolution | This is a transient server-side issue. Retry after a short delay. If the problem persists, contact the system administrator. |
| Source | DdosShieldMiddleware / RateLimiterMiddleware |
{
"type": "https://databuilder.polyxgo.com/api_docs#error-service-unavailable",
"title": "Service Unavailable",
"status": 503,
"detail": "The rate limiting backend is temporarily unavailable. The API uses a fail-closed strategy: when the rate limiter cannot verify your request count, all requests are rejected rather than silently bypassing the limit.",
"instance": "/api/v1/example"
}
Examples
# Select an endpoint to see examples
Sandbox GET
{
"message": "Click 'Run' to test"
}