Skip to content

Quickstart

Three steps, in this order: get a key, put credits on the account, convert a document. Signup to key takes under a minute and needs no card.

  1. Sign in at kaho.ai/app with your email address. There is no password — authentication is a magic link, so there is nothing to store, nothing to reset and nothing to stuff.

    Create a key under API keys → Create. Naming is required, not optional: one form field is the difference between an incident where you know which key leaked and one where you do not. Names are 1–64 characters and unique within a project.

    The plaintext key is shown exactly once, in the creation response. We store only a peppered HMAC of it, so there is no reveal button, because there is nothing to reveal. If you lose it, rotate it.

    Put the key somewhere your shell can see it
    export KAHO_API_KEY="kaho_sk_live_JhK2mQ9xT4vBn7RcW1sYdF6gPzL8aE3uH5iO0jN2kM4_x7Kp2q"

    Confirm it works. /v1/account is free and needs only the account:read scope, which the default Full access preset includes.

    Check the key and see the account
    curl -sS https://api.kaho.ai/v1/account \
    -H "Authorization: Bearer $KAHO_API_KEY"
    Response — a new free-tier account, abridged
    {
    "balance_credits": 200,
    "held_credits": 0,
    "debt_credits": 0,
    "credits_required_to_resume": 0,
    "currency_unit": "page",
    "trust_tier": "T0",
    "limits": {
    "requests_per_min": 5,
    "concurrency": 1,
    "max_pages_per_document": 10,
    "max_upload_bytes": 33554432,
    "storage_limit_bytes": 0,
    "storage_used_bytes": 0
    },
    "features": { "remote_fetch": false, "ocr": false, "provenance": false, "jobs": false }
    }

    A verified email alone puts you on the F0 free tier: 200 credits a month, documents up to 10 pages, 5 requests a minute, one concurrent request. That is enough to evaluate the API without paying anything. See Pricing and credits for F1, which is 1,000 credits a month and 20-page documents.

  2. Credits are prepaid. There is no subscription, no per-request fee and no minimum charge per document — you buy a balance and spend it a page at a time.

    Top up from Billing → Add credits in the console. Checkout is hosted by Stripe, so no card data touches us. Four packs, and the bonus is real credits rather than a discount code:

    PriceBase creditsBonusTotal creditsEffective per 1,000 pages
    $2550,00050,000$0.5000
    $100200,00010%220,000$0.4545
    $5001,000,00015%1,150,000$0.4348
    $2,5005,000,00020%6,000,000$0.4167

    Paid and bonus credits never expire. The $25 floor exists because card fees are 9% on a $5 charge and 4.1% on $25, and because removing sub-$5 charges removes the cheap card-testing probe entirely.

    Watch the balance move without opening the console:

    Balance, after the purchase settles
    curl -sS https://api.kaho.ai/v1/account \
    -H "Authorization: Bearer $KAHO_API_KEY" | jq '.balance_credits, .trust_tier'
  3. The shortest possible call: raw PDF bytes in, Markdown out, nothing else.

    One curl, Markdown on stdout
    curl -sS https://api.kaho.ai/v1/convert \
    -H "Authorization: Bearer $KAHO_API_KEY" \
    -H "Accept: text/markdown" \
    -H "Content-Type: application/pdf" \
    --data-binary @annual-report.pdf
    stdout
    ## Chairman's letter
    Trading conditions in the second half were materially better than we guided in March.
    | Segment | Revenue | Change |
    | ---------- | ------- | ------ |
    | Industrial | 412.9 | +8.1% |
    | Consumer | 188.3 | -2.4% |

    With Accept: text/markdown you get the body and nothing else; every field of the JSON response is still present, in x-kaho-* response headers. Drop the Accept header — JSON is the default — to get the full object:

    The full JSON response, five pages only
    curl -sS https://api.kaho.ai/v1/convert \
    -H "Authorization: Bearer $KAHO_API_KEY" \
    -H "Idempotency-Key: $(uuidgen)" \
    -F 'options={"pages":"1-5","page_markers":"rule"};type=application/json'
    Response, abridged
    {
    "id": "conv_01JQ8Z5T7B9KX2W4M6N0P3R5S7",
    "object": "conversion",
    "engine": "kaho-md-1.0.0",
    "created_at": "2026-08-17T18:22:31.114Z",
    "document": {
    "page_count": 42,
    "pages_selected": "1-5",
    "pages_selected_count": 5,
    "tagged": false,
    "language": "en-GB",
    "content_sha256": "3b1f0a9c…"
    },
    "markdown": "## Chairman's letter\n\n…",
    "pages": null,
    "warnings": [],
    "usage": {
    "pages_processed": 5,
    "pages_billed": 5,
    "pages_not_billed": [],
    "credits_charged": 5,
    "credit_balance_after": 219995,
    "line_items": [{ "kind": "page_convert", "quantity": 5, "credits": 5 }],
    "cache": "miss"
    },
    "timings_ms": { "parse": 41, "convert": 388, "encode": 12, "total": 441 }
    }

    Five pages, five credits, a quarter of a cent. There is no status field on a conversion: a 200 means we produced a result, and anything we could not do well is in warnings.

Exactly three encodings, and they may not be mixed. There are no precedence rules, by construction — precedence rules are where contracts rot. Sending query parameters alongside multipart or JSON is 400 query_options_not_allowed; any other content type is 415 unsupported_content_type.

Simplest, and the right choice for a one-shot conversion. Scalar options only — nested objects such as normalize need one of the other two encodings. A password cannot be sent this way.

Content-Type: application/pdf
curl -sS "https://api.kaho.ai/v1/convert?pages=1-5&page_markers=rule" \
-H "Authorization: Bearer $KAHO_API_KEY" \
-H "Content-Type: application/pdf" \
--data-binary @annual-report.pdf

Uploads are capped at 32 MiB on /v1/convert and 128 MiB on /v1/files. Stored files are deleted after 24 hours by default and 7 days at most, or immediately with DELETE /v1/files/{id}.

/v1/inspect answers “what is this document, and what will converting it cost?” without converting anything. With the default scan: "none" it is free: it reads the catalog, the page tree, the tagged flag, the permission bits, the form type and the bookmark tree, and loads no page.

Free structural probe and quote
curl -sS https://api.kaho.ai/v1/inspect \
-H "Authorization: Bearer $KAHO_API_KEY" \
Response, abridged
{
"object": "inspection",
"page_count": 312,
"tagged": true,
"encrypted": false,
"extraction_permitted": true,
"outline": { "status": "present", "entry_count": 137, "max_depth": 3 },
"quote": {
"pages": "1-200",
"billable_pages_max": 200,
"credits_max": 200,
"exceeds_sync_ceiling": true,
"line_items": [{ "kind": "page_convert", "quantity": 200, "credits": 200 }]
}
}

The quote never quotes a conversion the API would refuse. /v1/convert caps at 200 selected pages, so a 312-page document is quoted as its first 200 pages with exceeds_sync_ceiling: true, rather than as a 312-credit number that would produce 413 too_many_pages if you acted on it.

Two deeper scans exist and are selected with the JSON body encoding: scan: "sample" text-loads up to 20 evenly spaced pages and is free against a 2,000 pages/day budget, and scan: "full" text-loads every page and costs 1 credit per 100 pages, rounded up. A zero-balance account may run scan: "none"; it may not run the two that load pages.

Send an Idempotency-Key on every POST. It is optional and strongly recommended, and it is the difference between a network blip costing you nothing and costing you a second conversion.

A stable business key is better than a random one
curl -sS https://api.kaho.ai/v1/convert \
-H "Authorization: Bearer $KAHO_API_KEY" \
-H "Idempotency-Key: invoice-2026-Q2-84120" \

Keys are scoped to your organization rather than to the API key, so rotating a key in the middle of a retry cannot double-bill you. A replay of a completed request returns the original response with Idempotency-Replayed: true and is not billed again. A retry that arrives while the first attempt is still in flight is 409 idempotency_in_progress with Retry-After: 1. The same key with a different request body is 409 idempotency_conflict. Records live for 25 hours.

  • Authentication — key format, scopes, rotation, and leak response.
  • Pricing and credits — exactly what bills, and how holds and settlement work.
  • Page ranges — the pages grammar and how a selection turns into a bill.
  • Rate limits — the headers, and how to pace against them.
  • Errors — the full taxonomy, and what retryable means.