XBRL2JSON API v1
Programmatic access to your XBRL conversions, parse results, and extracted facts.
Contents
1. Authentication
All API requests require an API key passed in the X-API-KEY HTTP header.
You can create and manage your keys on the API Keys page.
curl -H "X-API-KEY: your_api_key_here" \
https://xbrl2json.co.uk/api/v1/me/quota-summary
2. Base URL & Versioning
All endpoints are prefixed with:
https://xbrl2json.co.uk/api/v1/
The version is embedded in the URL path. A custom X-Api-Version response header
is included in every response for programmatic version detection.
3. Response Format
All successful responses are wrapped in a standard JSON envelope:
Single-item response
{
"data": { ... }
}
Paginated response
{
"data": [ ... ],
"meta": {
"page": 1,
"pageSize": 25,
"totalCount": 142,
"totalPages": 6,
"hasNextPage": true,
"hasPreviousPage": false
}
}
4. Error Handling
Error responses use a consistent envelope with a machine-readable code and a human-readable message:
{
"error": {
"code": "NOT_FOUND",
"message": "Job not found."
}
}
| HTTP Status | Typical Codes | Meaning |
|---|---|---|
400 | VALIDATION_ERROR, INVALID_WEBHOOK_URL | Bad request or validation failure |
401 | UNAUTHORIZED | Missing or invalid API key |
403 | API_ACCESS_NOT_ALLOWED, QUOTA_EXCEEDED | Tier restriction or quota exceeded |
404 | NOT_FOUND, RESULT_NOT_READY, RESULT_EXPIRED | Resource not found or not yet available |
409 | DUPLICATE_JOB, NOT_CANCELLABLE | Conflict with current state |
429 | RATE_LIMITED | Too many requests (see Retry-After header) |
500 | INTERNAL_ERROR | Unexpected server error |
5. Rate Limits
The API enforces burst-rate limits to protect service stability. These are in addition to your monthly quota.
| Scope | Limit | Window |
|---|---|---|
| All API endpoints (per user) | 30 requests | 10 seconds |
| Job submission (per user) | 5 requests | 1 minute |
When rate-limited, you'll receive a 429 response with a Retry-After header
indicating how many seconds to wait before retrying.
6. Quick Start
Submit an XBRL file, poll for completion, then fetch the results — in three steps:
Step 1 — Submit a file
curl -X POST https://xbrl2json.co.uk/api/v1/jobs \
-H "X-API-KEY: your_api_key_here" \
-F "file=@report.xbrl"
# Response (202 Accepted):
# {
# "data": {
# "jobId": "01J5KXYZ...",
# "status": "Pending",
# "statusUrl": "https://xbrl2json.co.uk/api/v1/jobs/01J5KXYZ..."
# }
# }
Step 2 — Poll for status
curl https://xbrl2json.co.uk/api/v1/jobs/01J5KXYZ... \
-H "X-API-KEY: your_api_key_here"
# Poll every 1-2 seconds until "isTerminal": true
# {
# "data": {
# "jobId": "01J5KXYZ...",
# "status": "Succeeded",
# "isTerminal": true,
# "factsCount": 847,
# "resultUrl": "https://xbrl2json.co.uk/api/v1/parse-results/01J5KXYZ..."
# }
# }
Step 3 — Fetch results & facts
# Get parse result detail
curl https://xbrl2json.co.uk/api/v1/parse-results/01J5KXYZ... \
-H "X-API-KEY: your_api_key_here"
# Get extracted facts (paginated)
curl "https://xbrl2json.co.uk/api/v1/parse-results/01J5KXYZ.../facts?page=1&pageSize=50" \
-H "X-API-KEY: your_api_key_here"
7. Endpoints
POST
/api/v1/jobs
Submit an XBRL or iXBRL file for asynchronous processing. Returns 202 Accepted with a job ID for polling.
Request
Content-Type: multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
file | File | Yes | The XBRL/iXBRL file to process (max 50 MB for Pro tier). |
idempotencyKey | String | No | Client-supplied key to prevent duplicate submissions. |
webhookUrl | String | No | URL to receive a signed POST callback on completion. |
Responses
| Status | Description |
|---|---|
202 | Job accepted and queued. Body contains jobId, status, and statusUrl. |
400 | Validation failed (wrong file type, empty file, invalid webhook URL). |
401 | Missing or invalid API key. |
403 | Quota exceeded or tier restriction. |
409 | Duplicate idempotency key — job already exists. |
429 | Rate limited (max 5 submissions/minute). |
Example
curl -X POST https://xbrl2json.co.uk/api/v1/jobs \
-H "X-API-KEY: your_api_key_here" \
-F "file=@report.xbrl" \
-F "webhookUrl=https://example.com/webhook"
GET
/api/v1/jobs/{jobId}
Poll for the status and result of a previously submitted job. Includes a Retry-After: 2 header while the job is still processing.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
jobId | String (ULID) | The job identifier returned from the submit endpoint. |
Response Fields
| Field | Type | Description |
|---|---|---|
jobId | String | ULID public identifier. |
status | String | Pending, Running, Succeeded, Failed, Cancelled, or ResultExpired. |
isTerminal | Boolean | true when the job will not change further. Stop polling. |
requestedUtc | DateTime | When the job was submitted. |
startedUtc | DateTime? | When processing started (null if queued). |
completedUtc | DateTime? | When processing finished. |
durationMs | Int? | Processing time in milliseconds. |
factsCount | Int? | Number of facts extracted (on success). |
resultUrl | String? | URL to fetch the full parse result (on success). |
errorCode | String? | Machine-readable error code (on failure). |
errorMessage | String? | Human-readable error message (on failure). |
Example
curl https://xbrl2json.co.uk/api/v1/jobs/01J5KXYZ... \
-H "X-API-KEY: your_api_key_here"
POST
/api/v1/jobs/{jobId}/cancel
Cancel a pending job. Only the owning user can cancel, and only jobs in Pending status can be cancelled via the API.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
jobId | String (ULID) | The job identifier to cancel. |
Responses
| Status | Description |
|---|---|
200 | Job was cancelled. Body contains the updated job status. |
404 | Job not found or belongs to another user. |
409 | Job is not in a cancellable state (already running, completed, etc.). |
Example
curl -X POST https://xbrl2json.co.uk/api/v1/jobs/01J5KXYZ.../cancel \
-H "X-API-KEY: your_api_key_here"
GET
/api/v1/parse-results/{id}
Returns the parse result detail for a given job. Only available when the job status is Succeeded.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | String (ULID) | The ULID public identifier of the parse job. |
Responses
| Status | Description |
|---|---|
200 | Parse result detail. |
404 | Not found, not owned by you, or result not yet available. Check the error code for detail: RESULT_NOT_READY, JOB_FAILED, JOB_CANCELLED, RESULT_EXPIRED. |
Example
curl https://xbrl2json.co.uk/api/v1/parse-results/01J5KXYZ... \
-H "X-API-KEY: your_api_key_here"
GET
/api/v1/parse-results/{id}/facts
Returns a paginated list of extracted XBRL facts for a succeeded parse job.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | String (ULID) | The ULID public identifier of the parse job. |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
searchTerm | String | — | Free-text search against concept and value. |
concept | String | — | Prefix filter on concept name. |
unit | String | — | Exact filter on unit of measure. |
contextRef | String | — | Exact filter on context reference. |
numericOnly | Boolean | — | When true, only numeric facts. |
page | Int | 1 | 1-based page number. |
pageSize | Int | 25 | Items per page (max 200). |
Example
curl "https://xbrl2json.co.uk/api/v1/parse-results/01J5KXYZ.../facts?concept=Revenue&numericOnly=true&page=1&pageSize=50" \
-H "X-API-KEY: your_api_key_here"
GET
/api/v1/facts-by-filename
Retrieves the previously extracted facts for a document identified by its original file name. This is a convenience endpoint that lets you look up results without needing to track job IDs — just provide the file name you originally uploaded.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
fileName |
String | Yes | The original file name including extension (e.g. report.xbrl, accounts.html). Must match the name used at upload time. |
Response Headers
| Header | Description |
|---|---|
X-Document-PublicId | ULID of the matched uploaded document. |
X-ParseJob-PublicId | ULID of the matched parse job. |
X-Response-Source | StoredJson when the response came from the stored parser output, or ExtractedFacts if it was reconstructed from the database. |
Response Body
The response body is the raw JSON from the XBRL parser (or a JSON array of
extracted facts when falling back). It is not wrapped in the standard
{ "data": ... } envelope — this allows you to save or forward the output directly.
Responses
| Status | Code | Description |
|---|---|---|
200 | — | Facts JSON for the requested document. |
400 | VALIDATION_ERROR | fileName parameter is missing or empty. |
401 | UNAUTHORIZED / AUTH_REQUIRED | Missing or invalid API key. |
403 | QUOTA_EXCEEDED | Quota exceeded or tier restriction. |
404 | DOCUMENT_NOT_FOUND | No uploaded document with that file name exists in your account. |
404 | NOT_PROCESSED | The document exists but has not been successfully processed yet. |
404 | NO_RESULT | The job succeeded but no parse result record was found. |
404 | NO_FACTS | The stored JSON is missing and no extracted facts exist in the database. |
429 | RATE_LIMITED | Too many requests. |
Duplicate File Names
File names are not unique. If you uploaded the same file name multiple
times, this endpoint returns the facts from the most recent successfully processed
result. To target a specific run, use the
/api/v1/parse-results/{id}/facts endpoint
with the exact job ID instead.
Example
curl "https://xbrl2json.co.uk/api/v1/facts-by-filename?fileName=report.xbrl" \
-H "X-API-KEY: your_api_key_here"
# 200 OK
# X-Document-PublicId: 01J5KXYZ...
# X-ParseJob-PublicId: 01J5KABC...
# X-Response-Source: StoredJson
# Content-Type: application/json
#
# { ... raw parser JSON output ... }
Example (file not found)
curl "https://xbrl2json.co.uk/api/v1/facts-by-filename?fileName=missing.xbrl" \
-H "X-API-KEY: your_api_key_here"
# 404 Not Found
# {
# "error": {
# "code": "DOCUMENT_NOT_FOUND",
# "message": "No uploaded document with that file name was found."
# }
# }
GET
/api/v1/conversions
Returns a paginated list of your XBRL conversions with optional filtering.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
searchTerm | String | — | Free-text search against file name. |
parseJobStatus | String | — | Filter by job status (Pending, Running, Succeeded, Failed, Cancelled, ResultExpired). |
succeededOnly | Boolean | — | When true, only successful conversions. |
dateFrom | DateTime | — | Inclusive lower bound on submission date. |
dateTo | DateTime | — | Inclusive upper bound on submission date. |
page | Int | 1 | 1-based page number. |
pageSize | Int | 25 | Items per page (max 200). |
Example
curl "https://xbrl2json.co.uk/api/v1/conversions?succeededOnly=true&page=1&pageSize=10" \
-H "X-API-KEY: your_api_key_here"
GET
/api/v1/me/quota-summary
Returns the authenticated user's current quota entitlements and usage for the billing period.
Responses
| Status | Description |
|---|---|
200 | Quota summary including entitlements, current usage, and remaining allowances. |
404 | Quota summary could not be resolved. |
Example
curl https://xbrl2json.co.uk/api/v1/me/quota-summary \
-H "X-API-KEY: your_api_key_here"
8. Webhooks
Instead of polling, you can supply a webhookUrl when submitting a job.
When the job reaches a terminal state, the API will send a signed POST
request to your URL with the job status payload.
2xx status. If delivery fails, you can
always fall back to polling GET /api/v1/jobs/{jobId}.
9. Idempotency
To prevent duplicate job submissions (e.g. due to network retries), include an
idempotencyKey form field with your submit request. If a job with the
same key already exists for your account, the API returns 409 Conflict
with the existing job's identifier.
curl -X POST https://xbrl2json.co.uk/api/v1/jobs \
-H "X-API-KEY: your_api_key_here" \
-F "file=@report.xbrl" \
-F "idempotencyKey=my-unique-key-12345"
10. MCP (Model Context Protocol)
Overview
XBRL2JSON also acts as an MCP server, allowing AI assistants (such as Claude, GitHub Copilot, Cursor, and other MCP-compatible clients) to interact with your XBRL data through natural-language tool calls.
The MCP server exposes the same core functionality as the REST API — submitting XBRL files for processing, checking job status, retrieving parse results, exploring extracted facts, listing conversions, and viewing quota usage — but through the Model Context Protocol standard, using the Streamable HTTP transport.
Connecting
The MCP endpoint is available at:
https://xbrl2json.co.uk/mcp
Authentication uses the same X-API-KEY header as the REST API.
Your MCP client must send this header with every request to the MCP endpoint.
Available Tools
The MCP server exposes the following tools that AI clients can call:
get_quota_summary
Returns your current quota entitlements and usage, including uploads used this month, stored files, stored results, and storage consumed.
No parameters required.
list_conversions
Lists your XBRL conversions with optional filtering. Returns a paged list including job status, fact counts, and dates.
| Parameter | Type | Default | Description |
|---|---|---|---|
searchTerm | String | — | Free-text search against file name. |
parseJobStatus | String | — | Filter by status: Pending, Running, Succeeded, Failed, Cancelled, ResultExpired. |
succeededOnly | Boolean | — | When true, only successful conversions. |
page | Int | 1 | 1-based page number. |
pageSize | Int | 25 | Items per page (max 200). |
submit_job
Submit an XBRL or iXBRL file for asynchronous processing. The file content must be provided as a base64-encoded string. Returns a job ID that can be used with get_job_status and get_parse_result.
| Parameter | Type | Required | Description |
|---|---|---|---|
fileContentBase64 | String | Yes | Base64-encoded content of the XBRL / iXBRL file. |
fileName | String | Yes | Original file name including extension (e.g. report.xbrl, report.html). |
idempotencyKey | String | No | Optional client-supplied key to prevent duplicate submissions. |
get_job_status
Returns the current status of a previously submitted XBRL processing job. Use this to check whether a job is still running, has succeeded, or has failed.
| Parameter | Type | Required | Description |
|---|---|---|---|
jobId | String (ULID) | Yes | The ULID public identifier of the job. |
get_parse_result
Returns the full parse result detail for a completed job, including document info, parser version, fact/context/unit counts, and summary.
| Parameter | Type | Required | Description |
|---|---|---|---|
jobId | String (ULID) | Yes | The ULID public identifier of the parse job. |
get_facts
Returns a paginated list of XBRL facts extracted from a completed parse job. Supports filtering by concept name, unit, context reference, and numeric-only flag.
| Parameter | Type | Default | Description |
|---|---|---|---|
jobId | String (ULID) | — | Required. The ULID public identifier of the parse job. |
searchTerm | String | — | Free-text search against concept and value. |
concept | String | — | Prefix filter on concept name (e.g. ifrs-full:Revenue). |
unit | String | — | Exact filter on unit of measure (e.g. iso4217:GBP). |
contextRef | String | — | Exact filter on XBRL context reference. |
numericOnly | Boolean | — | When true, only numeric facts. |
page | Int | 1 | 1-based page number. |
pageSize | Int | 25 | Items per page (max 200). |
Client Configuration
Below are example configurations for popular MCP clients.
Claude Desktop
Add the following to your claude_desktop_config.json:
{
"mcpServers": {
"xbrl2json": {
"type": "streamable-http",
"url": "https://xbrl2json.co.uk/mcp",
"headers": {
"X-API-KEY": "your_api_key_here"
}
}
}
}
VS Code (GitHub Copilot)
Add the following to your .vscode/mcp.json file:
{
"servers": {
"xbrl2json": {
"type": "http",
"url": "https://xbrl2json.co.uk/mcp",
"headers": {
"X-API-KEY": "your_api_key_here"
}
}
}
}
Cursor
Add the following to your .cursor/mcp.json file:
{
"mcpServers": {
"xbrl2json": {
"url": "https://xbrl2json.co.uk/mcp",
"headers": {
"X-API-KEY": "your_api_key_here"
}
}
}
}
For interactive testing and full schema details, visit the Swagger UI. Need help? Contact us.