kobimusic

workspace

← learn

API quick start

the same tools over plain HTTP, with curl

Everything the workspace does goes through one small HTTP API, and you can call it yourself. Without a key, the API reads sheet music a little each week, counted by your address; every other tool needs an account. With an account, you can make an API key under “API keys” on the settings page and send it as a header (Authorization: Bearer kobi_sk_…). Then the credits come out of your account's instead. A credit is a page of music read, or a piece engraved, aligned or cleaned up.

A key uses the tools as you. Make it with the files box ticked and it can also see and change your files. It can never change your account.

one conversion

curl -F [email protected] -F [email protected] \
     -o sonata.mxl https://api.kobi.music/api/v1/tools/sheet-to-score
curl -F [email protected] -F partBook=true \
     -o quartet.mxl https://api.kobi.music/api/v1/tools/sheet-to-score
curl -H "Authorization: Bearer $KOBI_KEY" -F [email protected] -o take-3-aligned.mid https://api.kobi.music/api/v1/tools/beat-align
curl -H "Authorization: Bearer $KOBI_KEY" -F [email protected] -o take-3-clean.mid https://api.kobi.music/api/v1/tools/dehumanize
curl -H "Authorization: Bearer $KOBI_KEY" -F [email protected] -o take-3.mxl https://api.kobi.music/api/v1/tools/midi-to-sheet

Sheet music comes back as compressed MusicXML.

Parameters are form fields with the same names the builder shows (see nodes), or one params field holding JSON. The file comes back as the body. What the model had to say, such as the pages it read and which model ran, is in the X-Kobi-Report header as JSON. Send Accept: application/json to get both in one JSON answer instead.

long documents and many files

A call holds the connection open while it works, and a long document can take minutes. Ask to be answered at once, and ask after the work: send Prefer: respond-async with Accept: application/json, and a call that is not done in a moment answers 202 with a poll address. Ask that address every few seconds. It answers 202 while the work goes on, and then the file, as base64 in a JSON answer.

curl -s -o answer.json -H "Accept: application/json" -H "Prefer: respond-async" \
     -F [email protected] https://api.kobi.music/api/v1/tools/sheet-to-score
poll=$(jq -r '.poll // empty' answer.json)
while [ "$(jq -r '.status // empty' answer.json)" = running ]; do
  sleep 5; curl -s -o answer.json -H "Accept: application/json" "$poll"
done
jq -r '.outputs[0].base64' answer.json | base64 -d > sonata.mxl

One call is one piece: a PDF, or up to 50 page images. For many pieces, loop in your script, one call each, and keep at most 2 going at once. A call past that is answered busy, with Retry-After, and is worth repeating. Every answer carries X-RateLimit-Remaining, the credits you have left, and X-RateLimit-Reset, when they come back as a Unix time. Results and uploads are kept for a quarter of an hour, so save each one as it arrives. For a whole collection, read for institutions.

a whole flow

POST /run takes a flow and the files for its input nodes, and answers with what happened and links to the results. On the server a flow has nowhere to save to, so it ends in returns. It may use a tool 4 times at most. Longer batches run from the workspace, or one call each.

curl -H "Authorization: Bearer $KOBI_KEY" -F [email protected] -F [email protected] https://api.kobi.music/api/v1/run

endpoints

path
GET/statuswhich tools are up, which plan you are on, and how many credits are left
GET/nodesthe kinds of node, with their ports and parameters
POST/tools/:toolone use of a tool; with Prefer: respond-async, a long one answers at once with a job to ask after
GET/jobs/:ida tool's use, asked after: 202 while it runs (with progress, like "3 of 25 pages read", for a tool that says), then what it made
POST/runa whole flow; it waits a minute (or ?wait=seconds, up to 90), then answers with a run to ask after
POST/uploadsstage a file for a quarter of an hour; answers with a handle
GET/runs/:idhow a run is getting on, and where its results are
POST/mcpthe same, for an agent signed in to an account (see the agents quick start)
POST/mcp/guestthe same, for an agent with no account

when it says no

An error is JSON: { "error": { "code", "message", "retryable" } }. busy (503, with Retry-After) means the servers are busy, or you have as many calls going as one person may; the call is worth repeating. allowance (429) means the credits are used for now, and Retry-After says when they come back. plan (403) means the tool or model is for a level you are not at (see what each level can use). too-large (413) and unsupported (415) are about the file. bad-input (400) is about the request, and for a flow carries problems that point at the node, port or parameter at fault. When a call that was let in fails, an error with a charged number says how many credits it was charged all the same (a file the tool could not read costs one). A failure that was ours has none.