Skip to content
Docs
Esc
↑↓navigate↵open⌘Jpreview
On this page

Build over the HTTP API

Build and update Charming apps with plain web requests, no MCP server to add and nothing to install.

Charming has two ways in. One is MCP, where your client adds Charming as a connector and gets a set of tools. The other is this one: a plain HTTP API that any agent able to make web requests can call, with nothing installed and no server to add.

Both build the same apps in the same account. Pick whichever your agent can do.

When to use this path

Use the HTTP API when your client cannot add an MCP server, when adding one is more trouble than it is worth, or when your agent lives in a terminal or an editor and already makes web requests all day.

Most coding agents fall in that last group. Two cases do not: a chat surface that cannot make its own web requests, such as claude.ai or ChatGPT chat, and Microsoft 365 Copilot, which reaches Charming only through MCP. Setup steps per client are at AI clients.

Start here

Paste this into your agent:

Connect me to Charming and help me build my first app. Use Charming's
HTTP API. Ask before starting account pairing, wait for me to approve
it, then read https://charm.ing/docs/build-http.md and ask me what I
want to build.

That URL is the full build manual, written for the agent rather than for you. Your agent reads it, then asks what you want.

What your agent does

Creating an app with the existing contract needs no account and no token. Your agent posts the app’s code and gets back a live URL plus a token scoped to that one app:

jq -n --rawfile m module.js --rawfile u ui.js \
    '{module: $m, ui: $u, pair: true, label: "my agent"}' \
  | curl -sS https://charm.ing/app \
      -H 'Content-Type: application/json' -d @-

pair: true asks for a pairing alongside the app, so the app keeps working under your account once you claim it. Your agent shows you a link and a short code, you approve at charm.ing/pair, and it holds a token for your whole account from then on.

The existing contract uses these routes to build and run an app:

Route What it does
POST /app Create an app and get its URL
PUT /app/<id> Ship a code update
GET /app/<id>/describe List the app’s callable operations
<method> /app/<id>/api/<op> Call one operation with the method its route declares

An operation called with a method its route does not declare returns HTTP 405 method_not_allowed, and the Allow header names the declared method.

Selected authenticated authors can choose the ESM contract, which returns HTTP 202 before bundling. Poll the returned statusUrl until published; updates preserve the last working app while the build runs.

Where the detail lives

Execution failures

An executor_error may include details: { execution, operationId, reservationId? }. execution: "not_started" means the authority permanently ruled out execution of that operation. "may_have_run" means the operation may have executed; inspect its state before trying again. If admission failed before the authority returned an identity, details contains only execution: "may_have_run"; no operation or reservation ID is invented. Missing details, a timeout, or a lost connection do not prove nonexecution. These fields do not trigger an automatic retry. An invalid_module found after remote evaluation also carries execution: "may_have_run" and its operation identity, while retaining the validation message needed to fix the source. Read these fields from the response’s error.details.

Was this page helpful?