XBRL2JSON API v1

Programmatic access to your XBRL conversions, parse results, and extracted facts.

Interactive Swagger UI

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
Keep your keys secret. Do not commit them to source control or expose them in client-side code. Rotate keys immediately if you suspect they have been compromised.

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.

Change, 8 September 2026 — facts are served verbatim by default. The facts-by-filename and parse-results/{id}/facts endpoints, the fact exports and the MCP get_facts tool now return the filing exactly as parsed. The UK-specific processing that used to be applied silently (sign normalisation, derived balance-sheet totals) is an explicit opt-in: profile=uk-normalised. The former bare value normalised is no longer accepted.

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 StatusTypical CodesMeaning
400VALIDATION_ERROR, INVALID_WEBHOOK_URLBad request or validation failure
401UNAUTHORIZEDMissing or invalid API key
403API_ACCESS_NOT_ALLOWED, QUOTA_EXCEEDEDTier restriction or quota exceeded
404NOT_FOUND, RESULT_NOT_READY, RESULT_EXPIREDResource not found or not yet available
409DUPLICATE_JOB, NOT_CANCELLABLEConflict with current state
429RATE_LIMITEDToo many requests (see Retry-After header)
500INTERNAL_ERRORUnexpected server error

5. Rate Limits

The API enforces burst-rate limits to protect service stability. These are in addition to your monthly quota.

ScopeLimitWindow
All API endpoints (per user)30 requests10 seconds
Job submission (per user)5 requests1 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

FieldTypeRequiredDescription
fileFileYesThe XBRL/iXBRL file to process (max 50 MB for Pro tier).
idempotencyKeyStringNoClient-supplied key to prevent duplicate submissions.
webhookUrlStringNoURL to receive a signed POST callback on completion.
groupStringNoFree-text grouping tag (max 64 chars), e.g. a company registration number. Stored on the document so related filings can be filtered together on My Files / My Conversions.
Responses
StatusDescription
202Job accepted and queued. Body contains jobId, status, and statusUrl.
400Validation failed (wrong file type, empty file, invalid webhook URL).
401Missing or invalid API key.
403Quota exceeded or tier restriction.
409Duplicate idempotency key — job already exists.
429Rate 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 "group=12345678" \
     -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
ParameterTypeDescription
jobIdString (ULID)The job identifier returned from the submit endpoint.
Response Fields
FieldTypeDescription
jobIdStringULID public identifier.
statusStringPending, Running, Succeeded, Failed, Cancelled, or ResultExpired.
isTerminalBooleantrue when the job will not change further. Stop polling.
requestedUtcDateTimeWhen the job was submitted.
startedUtcDateTime?When processing started (null if queued).
completedUtcDateTime?When processing finished.
durationMsInt?Processing time in milliseconds.
factsCountInt?Number of facts extracted (on success).
resultUrlString?URL to fetch the full parse result (on success).
errorCodeString?Machine-readable error code (on failure).
errorMessageString?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
ParameterTypeDescription
jobIdString (ULID)The job identifier to cancel.
Responses
StatusDescription
200Job was cancelled. Body contains the updated job status.
404Job not found or belongs to another user.
409Job 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
ParameterTypeDescription
idString (ULID)The ULID public identifier of the parse job.
Responses
StatusDescription
200Parse result detail.
404Not 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
ParameterTypeDescription
idString (ULID)The ULID public identifier of the parse job.
Query Parameters
ParameterTypeDefaultDescription
searchTermString—Free-text search against concept and value.
conceptString—Prefix filter on concept name.
unitString—Exact filter on unit of measure.
contextRefString—Exact filter on context reference.
numericOnlyBoolean—When true, only numeric facts.
profileStringrawraw (default: the filing verbatim — no calculated facts, filed values) or uk-normalised (UK FRS 102/105 processing, with isCalculated / originalValueText marking every change).
pageInt11-based page number.
pageSizeInt25Items 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.

How it works: The API finds the most recent successfully processed result for the given file name within your account and returns its indexed facts — the same rows the /facts and export endpoints serve — in the parser-payload wire shape. A result indexed before September 2026 is re-indexed in place on its first request.
Query Parameters
ParameterTypeRequiredDescription
fileName String Yes The original file name including extension (e.g. report.xbrl, accounts.html). Must match the name used at upload time.
profile String No raw (default) serves the filing verbatim: every fact as the parser read it, nothing derived, nothing re-signed. This is the right view for any taxonomy, UK or otherwise. uk-normalised serves the indexed facts after UK FRS 102/105 processing: sign normalisation of net-assets style concepts and balance-sheet totals derived where the filing tagged none. Every fact the processor invented carries "isCalculated": true, and every value it changed carries "originalValueText" with the filed value. The body's top-level "profile" field and the X-Facts-Profile header confirm which view was served. Any other value is rejected with 400.
Response Headers
HeaderDescription
X-Document-PublicIdULID of the matched uploaded document.
X-ParseJob-PublicIdULID of the matched parse job.
X-Response-SourceStoredJson 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
StatusCodeDescription
200—Facts JSON for the requested document.
400VALIDATION_ERRORfileName parameter is missing or empty.
401UNAUTHORIZED / AUTH_REQUIREDMissing or invalid API key.
403QUOTA_EXCEEDEDQuota exceeded or tier restriction.
404DOCUMENT_NOT_FOUNDNo uploaded document with that file name exists in your account.
404NOT_PROCESSEDThe document exists but has not been successfully processed yet.
404NO_RESULTThe job succeeded but no parse result record was found.
404NO_FACTSThe stored JSON is missing and no extracted facts exist in the database.
429RATE_LIMITEDToo 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
ParameterTypeDefaultDescription
searchTermString—Free-text search against file name or group tag.
parseJobStatusString—Filter by job status (Pending, Running, Succeeded, Failed, Cancelled, ResultExpired).
succeededOnlyBoolean—When true, only successful conversions.
dateFromDateTime—Inclusive lower bound on submission date.
dateToDateTime—Inclusive upper bound on submission date.
pageInt11-based page number.
pageSizeInt25Items 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
StatusDescription
200Quota summary including entitlements, current usage, and remaining allowances.
404Quota 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.

Webhook delivery: The callback is attempted once with a 15-second timeout. Ensure your endpoint responds with a 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.

Tip: Use the same API key you created on the API Keys page. The MCP server enforces the same user-scoped security — you can only access your own jobs, results, and facts.

Typical workflow. Ask your assistant in natural language and it calls the tools for you. A submission flows submit_job → poll get_job_status until isTerminal is true → get_parse_result for the summary and get_facts to page through extracted facts. Use list_conversions to find earlier jobs and get_quota_summary to check usage.

Every tool except submit_job is read-only, all tools return structured output (with an output schema clients can validate against), and failures are reported as MCP tool errors so a client can tell a failure apart from a successful result.

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.

ParameterTypeDefaultDescription
searchTermString—Free-text search against file name or group tag.
parseJobStatusString—Filter by status: Pending, Running, Succeeded, Failed, Cancelled, ResultExpired.
succeededOnlyBoolean—When true, only successful conversions.
pageInt11-based page number.
pageSizeInt25Items 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.

ParameterTypeRequiredDescription
fileContentBase64StringYesBase64-encoded content of the XBRL / iXBRL file.
fileNameStringYesOriginal file name including extension (e.g. report.xbrl, report.html).
idempotencyKeyStringNoOptional client-supplied key to prevent duplicate submissions.
groupStringNoOptional free-text grouping tag (max 64 chars), e.g. a company registration number, so related filings can be filtered together later.

Size limit: MCP submissions are capped at ~7 MB because the file travels base64-encoded inside the request. For larger files, use the REST POST /api/v1/jobs multipart endpoint instead.

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.

ParameterTypeRequiredDescription
jobIdString (ULID)YesThe 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.

ParameterTypeRequiredDescription
jobIdString (ULID)YesThe 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.

ParameterTypeDefaultDescription
jobIdString (ULID)—Required. The ULID public identifier of the parse job.
searchTermString—Free-text search against concept and value.
conceptString—Prefix filter on concept name (e.g. ifrs-full:Revenue).
unitString—Exact filter on unit of measure (e.g. iso4217:GBP).
contextRefString—Exact filter on XBRL context reference.
numericOnlyBoolean—When true, only numeric facts.
profileStringrawraw (default: the filing verbatim — no calculated facts, filed values) or uk-normalised (UK FRS 102/105 processing, with isCalculated / originalValueText marking every change).
pageInt11-based page number.
pageSizeInt25Items per page (max 200).

Resources

As well as tools, the server exposes a job's output as MCP resources — addressable, attachable content under the xbrl2json:// URI scheme. An assistant can attach these directly as context instead of issuing a tool call. Resources are scoped to your API key, and each read counts against your monthly API quota the same as a tool call.

URI templateContent
xbrl2json://jobs/{jobId}/resultParse-result detail (job status, parser version, fact/context/unit counts, summary) as JSON.
xbrl2json://jobs/{jobId}/factsExtracted facts as a JSON export envelope (capped at 10,000 rows; wasTruncated signals more).
xbrl2json://jobs/{jobId}/jsonThe converted JSON output. Requires a plan that includes JSON download; capped for context use — use the REST download endpoint for very large or complete files.

Prompts

The server also offers reusable prompts — ready-made templates for common analyses that your client can surface (often as slash-commands). Each expands into an instruction that drives the tools and resources above; the data work happens when the assistant runs them.

PromptArgumentsProduces
summarize_filingjobIdA plain-English summary: reporting entity, period, and headline financials.
extract_financialsjobId, statement (optional)A clean table of financial-statement line items for the chosen statement.
compare_filingsjobId1, jobId2A side-by-side comparison of key metrics with the change between the two filings.

Client Configuration

Below are example configurations for popular MCP clients.

Claude Code (CLI)

Register the server with a single command:

claude mcp add --transport http xbrl2json https://xbrl2json.co.uk/mcp \
  --header "X-API-KEY: your_api_key_here"
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"
      }
    }
  }
}
Keep your API key secret. If you store MCP client configuration in a repository, use environment variables or a secrets manager instead of hard-coding your key.

For interactive testing and full schema details, visit the Swagger UI. Need help? Contact us.