flatmark Convert API
The Convert API from flatmark — 3 operation(s) for convert.
The Convert API from flatmark — 3 operation(s) for convert.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/flatmark-dev:flatmark-dev-convert-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: flatmark Convert API
description: 'Document to Markdown API and MCP server for PDF, Word, PowerPoint, Excel and HTML. OCR queue for large files. Hosted in Germany.
Base URL: `https://api.flatmark.dev`.
### Authentication
Send your key in the `X-API-Key` header. Calls without a key run anonymously at
a lower rate limit per IP address.
### Rate limits
Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and
`X-RateLimit-Reset` (seconds until the window resets). Over-budget calls return
`429` with a `Retry-After` header. Check your live budget at `GET /v1/me`.
### Pagination
List endpoints return a keyset envelope: `{"items": [...], "next_cursor": "..."}`.
Pass `next_cursor` back as the `?cursor=` query param for the next page; it is
`null` on the last page.
### Errors
Errors are RFC 9457 `problem+json` with a
stable machine-readable **`code`** (e.g. `rate_limited`, `credits_exhausted`,
`validation_error`). Branch on `code`. The `title` and `detail` text may change.
### Quickstart
```sh
curl -H "X-API-Key: $API_KEY" https://api.flatmark.dev/v1/me
```'
version: '1'
servers:
- url: https://api.flatmark.dev
tags:
- name: Convert
paths:
/v1/convert:
post:
tags:
- Convert
summary: Convert a document to Markdown in one call
description: 'Converts one document up to 8 MB and returns the Markdown in the response.
Accepted types: PDF (`application/pdf`), Word `.docx`, PowerPoint `.pptx`,
Excel `.xlsx`, HTML (`text/html`) and plain text (`text/plain`). The
Content-Type of the file part decides how it is read. Conversion uses
MarkItDown. PDFs come back as plain text without headings and without OCR.
For scans, tables and page numbers, use the queue (`POST /v1/convert/jobs`).
Works without an API key at the anonymous rate limit. With a key, a
rejected or failed call costs no credits.
**Credits:** 1 per call.'
operationId: convert_document
requestBody:
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/Body_convert_document'
required: true
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/SyncConvertResponse'
'402':
description: Your credit balance is used up (`credits_exhausted`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'413':
description: The file is larger than 8 MB (`payload_too_large`). Use the queue.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'415':
description: The file type is not accepted, or the file does not match its declared type (`unsupported_media_type`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'422':
description: The document could not be converted, for example because it is damaged or password-protected (`conversion_failed`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'429':
description: Too many requests. Wait for the number of seconds in `Retry-After`.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'500':
description: The conversion stopped unexpectedly (`engine_failed`). Try again.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'503':
description: A service this call depends on is unavailable. Try again later.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'504':
description: The conversion took too long and was stopped (`engine_timeout`). Use the queue.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
security:
- APIKeyHeader: []
x-connector:
kind: action
sample_file: /app-static/samples/sample.pdf
x-credits-cost: 1
/v1/convert/jobs:
post:
tags:
- Convert
summary: Queue a document for conversion with OCR and tables
description: 'Queues one document up to 25 MB and 200 pages for conversion with Docling.
Accepted types are the same as for `POST /v1/convert`. The queue runs OCR
(text recognition) and recognizes tables, headings and reading order. A
conversion may take up to about 2 minutes; longer ones are stopped and fail.
Poll `GET /v1/jobs/{id}` (free) until `status` is `succeeded` or `failed`,
then download the result from `result_url` (free). The result is Markdown, or
the DoclingDocument JSON with `?format=json`.
With `webhook_url`, the job''s final state is POSTed there as JSON
(`job_id`, `status`, `result`, `error`). The request carries
`X-Appkit-Signature: sha256=`, an HMAC-SHA256 of the raw request body
keyed with the `webhook_secret` from this response. `webhook_secret` is shown
only once. A delivery that fails is retried, 3 attempts in total.
Requires an API key. The credits are charged at submission and refunded if
the job fails. The uploaded file is deleted when the job finishes. Results
are kept for 7 days after submission.
**Credits:** 10 per call.'
operationId: submit_conversion_job
requestBody:
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/Body_submit_conversion_job'
required: true
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/JobSubmitResponse'
'401':
description: No valid API key in the `X-API-Key` header.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'402':
description: Your credit balance is used up (`credits_exhausted`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'413':
description: The file is larger than 25 MB (`payload_too_large`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'415':
description: The file type is not accepted (`unsupported_media_type`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'422':
description: '`webhook_url` is not a public http or https address (`invalid_webhook_url`).'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'429':
description: Too many requests, or your plan's number of unfinished queued jobs is reached (`too_many_jobs`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'503':
description: A service this call depends on is unavailable. Try again later.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
security:
- APIKeyHeader: []
x-connector:
kind: job
job:
result: get_conversion_result
poll: get_job
sample_file: /app-static/samples/sample.pdf
x-credits-cost: 10
/v1/convert/jobs/{job_id}/result:
get:
tags:
- Convert
summary: Download a queued job's Markdown or JSON
description: 'Returns the output of one of your finished queued jobs.
Markdown (`text/markdown`) by default, or the DoclingDocument JSON
(`application/json`) with `?format=json`. The JSON carries page numbers for
PDF, slide numbers for PowerPoint and sheet names for Excel.
**Credits:** free. This endpoint is not metered.'
operationId: get_conversion_result
security:
- APIKeyHeader: []
parameters:
- name: job_id
in: path
required: true
schema:
type: string
title: Job Id
- name: format
in: query
required: false
schema:
enum:
- markdown
- json
type: string
description: '`markdown` (default) or `json` for the DoclingDocument structure file.'
default: markdown
title: Format
description: '`markdown` (default) or `json` for the DoclingDocument structure file.'
responses:
'200':
description: The converted document.
content:
text/markdown:
schema:
type: string
application/json:
schema:
type: object
'404':
description: No job with this id in your account (`not_found`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'409':
description: The job has not finished (`job_not_ready`), or it failed (`job_failed`, with the reason in `detail`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'410':
description: The result was deleted 7 days after submission (`result_expired`).
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'422':
description: '`format` is not `markdown` or `json`.'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'429':
description: Too many requests. Wait for the number of seconds in `Retry-After`.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
x-connector:
kind: result
x-credits-cost: 0
components:
schemas:
SyncConvertResponse:
properties:
markdown:
type: string
title: Markdown
description: The document as Markdown.
meta:
additionalProperties: true
type: object
title: Meta
description: 'Details about the source: `filename`, and `title` when the document has one.'
type: object
required:
- markdown
title: SyncConvertResponse
description: The result of a direct conversion.
Problem:
description: The RFC 9457 error body. Every error response uses it.
properties:
type:
default: about:blank
description: Problem type URI (RFC 9457).
title: Type
type: string
title:
description: Short human-readable summary of the status.
title: Title
type: string
status:
description: The HTTP status code, repeated in the body.
title: Status
type: integer
detail:
description: What went wrong with this request.
title: Detail
type: string
instance:
description: The request path that produced the error.
title: Instance
type: string
code:
description: Stable machine-readable error code. Branch on this, not on the text.
title: Code
type: string
request_id:
anyOf:
- type: string
- type: 'null'
default: null
description: Correlation id for this request; quote it when asking for support.
title: Request Id
errors:
anyOf:
- items:
additionalProperties: true
type: object
type: array
- type: 'null'
default: null
description: Per-field validation failures. Present on 422 only.
title: Errors
upgrade_url:
anyOf:
- type: string
- type: 'null'
default: null
description: Where to add credits or move to a larger plan. Present on 402/403/429.
title: Upgrade Url
required:
- title
- status
- detail
- instance
- code
title: Problem
type: object
Body_convert_document:
properties:
file:
type: string
contentMediaType: application/octet-stream
title: File
description: The document, sent as multipart form data with its Content-Type.
type: object
required:
- file
title: Body_convert_document
JobSubmitResponse:
properties:
job_id:
type: string
title: Job Id
description: The job id.
status:
type: string
title: Status
description: '`queued` at submission.'
webhook_secret:
anyOf:
- type: string
- type: 'null'
title: Webhook Secret
description: The key for checking the webhook signature. Only set when you sent `webhook_url`, and only shown in this response.
result_url:
type: string
title: Result Url
description: Where to download the result once the job succeeded.
poll_url:
type: string
title: Poll Url
description: Where to check the job's status.
type: object
required:
- job_id
- status
- result_url
- poll_url
title: JobSubmitResponse
description: A queued conversion job.
Body_submit_conversion_job:
properties:
file:
type: string
contentMediaType: application/octet-stream
title: File
description: The document, sent as multipart form data with its Content-Type.
webhook_url:
anyOf:
- type: string
- type: 'null'
title: Webhook Url
description: Optional. A public http or https URL that receives a POST when the job finishes.
type: object
required:
- file
title: Body_submit_conversion_job
securitySchemes:
APIKeyHeader:
type: apiKey
in: header
name: X-API-Key