Convert Endpoints
Conversion is part of All tools. A start needs the
relevant scope and enough credits, and convert.file must be available in
/v1/health. Free credits also follow the
free limits: free accounts and guests may convert
only their authorized, scanned sources up to 2 MiB.
Office and PDF converters run without network access in an isolated filesystem
with bounded time, memory/address space, process count and output size. If the
required isolation cannot start, conversion is unavailable
(provider_unavailable) and converter work is not charged. Unsupported/empty documents and conversion failures retain
their documented settlement rules; isolation does not guarantee every document
is convertible.
Convert endpoints create billable asynchronous operations that transform a scanned stored file or reusable operation artifact into Markdown, plain text, or safe HTML. The converted output is stored as a protected operation artifact.
This endpoint is preview. Preview means the contract may still evolve before stable release.
Shared Access
- Access: Paid plans that include this family, or free credits (guest trial or verified account) within the free limits.
- Operation family: Conversion
- Scope:
api:convert:write - Idempotency:
Idempotency-Keyheader required for live requests - Sources: scanned
file_idor customer-visible reusableartifact_id
Unsupported fields are rejected with validation_failed. Convert endpoints do
not accept raw file bytes, URLs, provider task ids, storage paths, or bulk
export options.
POST/v1/convert/file
Creates a file conversion operation.
Request
{
"source": {
"type": "file_id",
"id": "fil_01jz7h0a1b2c3d4e5f6g7h8j"
},
"output_format": "markdown",
"include_source_metadata": true,
"cleanup": "none"
}
Curl example:
curl -X POST https://www.chab.ai/v1/convert/file \
-H "Authorization: Bearer CHAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: convert-file-001" \
-d '{
"source": {
"type": "file_id",
"id": "fil_01jz7h0a1b2c3d4e5f6g7h8j"
},
"output_format": "markdown"
}'
CLI-shaped client example:
convert file fil_01jz7h0a1b2c3d4e5f6g7h8j \
--source-type file_id \
--output-format markdown \
--idempotency-key convert-file-001 \
--wait
Fields:
source.type: requiredfile_idorartifact_id. Afile_idmust be in the available scanned state; both source types remain subject to current token and project authority.source.id: required source identifier.output_format: requiredmarkdown,text, orsafe_html.dry_run: optional boolean. Defaults tofalse.include_source_metadata: optional boolean. Defaults totrue.cleanup: optional string. Onlynoneis accepted.callback_url,callback_secret,callback_events, andcallback_notify_on_expiration: optional one-off operation callback fields.
Supported Matrix
| Source category | Markdown | Text | Safe HTML |
|---|---|---|---|
| Plain text | Yes | Yes | Yes |
| Markdown | Yes | Yes | Yes |
| HTML | Yes | Yes | Yes |
| Word (DOCX, DOC), OpenDocument text (ODT), RTF | Yes | Yes | Yes |
| Spreadsheets (XLSX, XLS, ODS) | Yes | Yes | Yes |
| CSV and TSV | Yes | Yes | Yes |
| Slide decks (PPTX, PPT, ODP) | Yes | Yes | Yes |
| E-books (EPUB) | Yes | Yes | Yes |
| PDF with extractable text | Yes | Yes | No |
How the structure carries over:
- Spreadsheets: every sheet becomes a table under a heading with the sheet's
name, in workbook order. CSV and TSV files become one table. Cells show the
value as displayed in the sheet. Each table keeps its header row and the
first 1,000 data rows and the first 50 columns; when rows are cut, the
output says so under the table and the result carries a
result_truncatedwarning. - Slide decks: every slide becomes a section,
Slide 3: Title, with the slide's text as a list. Speaker notes are not included. - E-books: the chapters in reading order, with headings, lists and emphasis. Styles, scripts and images are dropped.
- Macro-enabled Office files (DOCM, XLSM, PPTM) are refused at upload, and macros in other files never run.
Unsupported source categories return unsupported_file_type. Unsupported
source/output pairs return unsupported_conversion_pair.
An eligible source that exceeds the conversion limit returns the stable
source_too_large error code. This replaces the earlier field-only
validation_failed response for oversized conversion artifacts.
Safe HTML output uses an allowlist suitable for display or storage. It removes scripts, styles, form controls, images, embedded media, external resource loads, event handlers, classes, inline style, and unsafe link protocols.
Pricing
Conversion pricing is based on Chab's trusted source metadata, not on customer-supplied fields.
| Source category | Credits |
|---|---|
| Plain text, Markdown, HTML, CSV or TSV | 5 |
| Word, Excel, PowerPoint, OpenDocument, RTF or EPUB | 15 |
| PDF with extractable text | 20 |
Validation failures before converter work are not charged. A PDF that has no
extractable text, or a spreadsheet, deck or book with nothing to read, fails
with unsupported_file_content and releases the hold.
Converter timeouts or failures after conversion work starts can be charged up
to the reserved estimate.
See Credits and Billing.
Async Response
Live requests return 202 Accepted with the standard operation envelope:
{
"operation": {
"id": "op_01JZ7H0A1B2C3D4E5F6G7H8J9K",
"status": "queued",
"operation_key": "convert.file",
"family": "convert",
"status_url": "/v1/operations/op_01JZ7H0A1B2C3D4E5F6G7H8J9K",
"result_url": "/v1/operations/op_01JZ7H0A1B2C3D4E5F6G7H8J9K/result",
"estimated_credits": 5,
"result_available": false,
"warnings": []
},
"meta": {
"request_id": "req_123",
"credits": {
"estimated": 5,
"reserved": 5,
"currency": "credit"
}
}
}
Poll the operation status URL until it reaches a terminal state, or fetch the
result URL after result_available becomes true.
Dry Run
Set dry_run: true to validate request shape, source metadata, plan access,
limits, provider readiness, callback shape, budget, spend threshold, and credit
availability without creating an operation.
Dry runs do not require or persist an idempotency key, do not reserve credits, do not read source content, and do not create operation rows, callback secrets, artifacts, provider tasks, usage counters, or rate-bucket hits.
{
"source": {
"type": "artifact_id",
"id": "art_01JZ7H0A1B2C3D4E5F6G7H8J9K"
},
"output_format": "text",
"dry_run": true
}
Dry-run response:
{
"data": {
"operation_key": "convert.file",
"family": "convert",
"estimated_credits": 5,
"currency": "credit",
"source": {
"type": "artifact",
"id": "art_01JZ7H0A1B2C3D4E5F6G7H8J9K",
"mime_type": "text/markdown",
"source_format": "markdown",
"source_state": "available",
"byte_size": 4096,
"checksum": "sha256:example",
"filename": "brief.md"
},
"output_format": "text",
"cleanup": "none",
"include_source_metadata": true,
"callback": {
"requested": false,
"enabled": false,
"url": null,
"events": [],
"notify_on_expiration": false,
"secret_staged": false
},
"live_request": {
"requires_idempotency_key": true
}
},
"meta": {
"request_id": "req_123",
"dry_run": true
}
}
Result And Artifact
Successful conversion results include conversion facts and one
customer-visible artifact with role converted_output.
{
"data": {
"result": {
"output_format": "markdown",
"conversion_method": "markdown",
"output_mime_type": "text/markdown",
"output_byte_size": 2048,
"output_checksum": "sha256:example",
"artifact_role": "converted_output",
"confidence": 1,
"source": {
"type": "artifact",
"id": "art_01JZ7H0A1B2C3D4E5F6G7H8J9K",
"mime_type": "text/markdown",
"source_format": "markdown",
"source_state": "available",
"byte_size": 4096,
"checksum": "sha256:source",
"filename": "brief.md"
}
},
"artifacts": [
{
"id": "art_01JZ7H0A1B2C3D4E5F6G7H8J9K",
"type": "text",
"role": "converted_output",
"mime_type": "text/markdown",
"byte_size": 2048,
"checksum": "sha256:example",
"filename": "brief.md",
"metadata_url": "/v1/operations/op_01JZ7H0A1B2C3D4E5F6G7H8J9K/artifacts/art_01JZ7H0A1B2C3D4E5F6G7H8J9K",
"download_url": "/v1/operations/op_01JZ7H0A1B2C3D4E5F6G7H8J9K/artifacts/art_01JZ7H0A1B2C3D4E5F6G7H8J9K/download",
"expires_at": "2026-07-17T12:00:00+00:00"
}
],
"warnings": [],
"result_expires_at": "2026-07-17T12:00:00+00:00"
},
"meta": {
"request_id": "req_123"
}
}
Download the converted file through the artifact download_url before
expires_at. Artifact metadata and downloads require bearer authentication.
For a conversion created through hosted MCP, use chab_operation_artifact
with content: "inline" for paged text, following next_offset, or
content: "link" for a downloadable file. See Hosted MCP.
When include_source_metadata is false, the result omits the source object
from data.result; artifact metadata remains available.
Source State Errors
Source references use the shared artifact-input behavior. Missing artifacts,
cross-team artifacts, artifacts the key cannot read, and artifacts whose stored
bytes are no longer readable return not_found without disclosing which
condition applied.
| Code | HTTP | Retry | Chargeable | What to do |
|---|---|---|---|---|
not_found |
404 | No | No | Check the artifact id and make sure it belongs to the same team and token context. |
artifact_expired |
410 | No | No | Use a non-expired artifact. |
Conversion Errors
| Code | HTTP | Retry | Chargeable | What to do |
|---|---|---|---|---|
unsupported_file_type |
422 | No | No | Use a supported source category. |
unsupported_conversion_pair |
422 | No | No | Pick an output format supported by the source category. |
unsupported_file_content |
422 | No | No | Use a file with extractable text. |
conversion_timeout |
504 | Yes | Yes, after work starts | Retry later or reduce source complexity. |
conversion_failed |
502 | No | Yes, after work starts | Check the source and output format before retrying. |
artifact_creation_failed can also occur if Chab cannot persist the converted
artifact. In that case the hold is released because the output is not available.
Callbacks
Callbacks use the standard operation callback contract. Terminal callback
payloads use the same operation shape as polling, including operation.status,
operation.public_error_code, settlement facts when available, and artifact
references when the result succeeded. Use the operation result URL to download
the retained converted artifact.