API reference
HTTP API
The mux API is JSON over HTTPS. It is what muxcode, the MCP server and the web app use to reach a workspace’s code index, its repositories and its sandboxes, and anything you build can use it the same way.
Every path below is under the base URL https://usemux.com/api.
Authentication
Section titled “Authentication”Send a workspace key
A workspace key is a bearer token: Authorization: Bearer hk_live_…. Each key belongs to exactly one workspace and carries a role, and it can never do more than the person who minted it can do today. A key whose owner loses access stops working with them.
Workspace owners mint keys in the app under Settings, then Access. A key is shown once, when it is minted; mux keeps only its hash.
Roles, from least to most: viewer, agent, editor, owner. Each route below names the least role it needs.
The web app calls the same routes with the signed-in person’s session cookie instead of a key. Routes marked signed-in person accept only that: a key, however senior, is refused with 403 human_gate.
curl https://usemux.com/api/v1/vaults/01J9Z3K8QF/workspace \ -H "Authorization: Bearer $MUX_API_KEY"Errors
Section titled “Errors”The error shape
mux answers with a conventional status code and, for every error, one JSON envelope: a stable code to branch on and a message written to be shown to a person.
400 validation_error- the body or a parameter is not what the route accepts.invalid_jsonwhen the body is not JSON at all.401 unauthenticated- no key or session, or a key that is revoked or expired.403 forbidden- your role is below the route’s.human_gatewhen the route needs a signed-in person.plan_refusedandplan_limitwhen the plan does not include it.404 not_found- no such thing, or one your credential cannot see. A workspace in another organization answers404, never403, so a key cannot learn what exists elsewhere.409- the request conflicts with the workspace’s state, such asno_repositoriesorrefresh_in_progress.429- a rate limit; see below.5xx- mux or a service behind it did not answer.503 index_unavailableis safe to retry.
{ "error": { "code": "not_found", "message": "Vault not found." }}Rate limits
Section titled “Rate limits”Two meters per organization
Every /v1 request draws from two meters kept per organization: a per-minute burst bucket and a monthly ceiling by UTC calendar month. Each response reports both.
X-RateLimit-Limit,X-RateLimit-RemainingandX-RateLimit-Reset(Unix seconds) for the burst bucket.X-Quota-LimitandX-Quota-Remainingfor the month.
Past either meter the answer is 429 with Retry-After, and scope names the meter. burst clears within the minute. monthly clears at the start of the next UTC month, so do not retry it in a loop. This one answer is a flat body rather than the error envelope.
Device sign-in is limited by address instead, and refuses a start when the limiter cannot answer.
| Plan | Workspaces | Repositories indexed | Refresh | Search by meaning | Requests/min | Requests/month |
|---|---|---|---|---|---|---|
| Hobby | 1 | 1 | on request | no | 30 | 50,000 |
| Pro | 5 | 20 | on push | yes | 120 | 500,000 |
| Team | 25 | 20 | on push | yes | 300 | 2,000,000 |
HTTP/1.1 429 Too Many RequestsRetry-After: 12X-RateLimit-Limit: 120X-RateLimit-Remaining: 0X-RateLimit-Reset: 1727000060{ "error": "Rate limit exceeded", "scope": "burst", "retryAfter": 12}Workspaces
Section titled “Workspaces”A workspace holds the repositories you index, the people and keys that can reach it, and its sandbox runs. In the API a workspace is a vault, and its id is the vaultId in every path.
Retrieve a workspace
GET /v1/vaults/:vaultId/workspace
Who can call itviewer
Describes the workspace a key or session reaches, and what its plan lets a client offer. Read capabilities before searching: a workspace without semantic should be offered pattern search only.
Returns
-
planstring free(Hobby),pro,proplusorteam.-
rolestring - The caller’s role in this workspace.
-
trialobject | null - The caller’s trial, in the device sign-in’s shape but never with a
keychainToken;nullwhen they have none. -
metersobject - Where the caller stands against their caps, in the device sign-in’s shape.
-
capabilitiesobject semantic,structuralSearchandrepositoryFilters.semanticis false on Hobby.-
indexobject - The number of repositories indexed, file and chunk counts,
lastSuccessAtin milliseconds, and theembeddingVersionthe index was built with. -
managementUrlstring - Where the workspace is managed in the app.
curl https://usemux.com/api/v1/vaults/01J9Z3K8QF/workspace \ -H "Authorization: Bearer $MUX_API_KEY"{ "managementUrl": "https://usemux.com/app/workspaces?corpus=01J9Z3K8QG", "organizationId": "org_2Yc81", "workspaceName": "Acme", "corpusId": "01J9Z3K8QG", "corpusName": "Code corpus", "plan": "pro", "role": "agent", "capabilities": { "semantic": true, "structuralSearch": true, "repositoryFilters": true }, "index": { "embeddingVersion": "Snowflake/snowflake-arctic-embed-xs", "repositories": 2, "files": 1234, "chunks": 5678, "lastSuccessAt": 1727000000000 }}List workspaces
GET /v1/vaults
Who can call itany key or session
A signed-in person gets every workspace they hold a grant on, oldest first, with their role in each. A key gets its one workspace, without role, or an empty list once that workspace is deleted.
Query parameters
-
deleted1 - Signed-in person only: list the deleted workspaces you own instead. Each can be restored for 30 days with
POST /v1/vaults/:vaultId/restore.
curl https://usemux.com/api/v1/vaults \ -H "Authorization: Bearer $MUX_API_KEY"[ { "id": "01J9Z3K8QF", "orgId": "org_2Yc81", "name": "Acme", "slug": "acme", "createdAt": 1726500000000 }]Code search
Section titled “Code search”One route answers every question you can ask the index. The body names an operation and its arguments, the same five tools the MCP server gives an agent, plus the code graph and context packets.
Query the index
POST /v1/vaults/:vaultId/corpus/query
Who can call itviewer
Every result carries repository, path, line, endLine, score, excerpt and the headSha it was read at; search_code results also carry language. The body is capped at 16 KiB.
Body
-
organizationIdstring required - The organization the workspace belongs to. Any other answers
404 not_found. -
operationstring required - One of
corpus_status,list_repositories,grep_code,search_code,ask_code,get_contextortrace_code. -
argumentsobject - The operation’s arguments; see Operations below.
-
recordboolean falsekeeps the search out of the workspace’s analytics. Defaults totrue.
Operations
-
corpus_statusno arguments - Whether the workspace is indexed, its repositories and their state, the plan and its limits. Read from stored state; it never wakes the index.
-
list_repositoriesno arguments {repositories}, each with itsnameand indexedheadSha.-
grep_codepattern · path, language, repository - A structural match against the syntax tree, not a text search. In a pattern a backslash marks a placeholder:
foo(\X)is a call with one argument,foo(\(ARGS*\))a call with any number. Answers{results, truncated}. -
search_codequery · limit, repository, language, path - Results ranked by meaning, so a search can find code that never uses its words. Pro and Pro+.
-
ask_codequery - The passages that bear on a question, as
grounding. It does not write the answer:answerisnull, and your model reads the passages. Pro and Pro+. -
trace_coderepository, path · symbol, limit - One file on the code graph: what it
defines,imports, isimportedBy, itstestsand what it istestedBy, the routes it calls and is called from, and itsowners. -
get_contexttask · repositories, revisions, changedPaths, tokenBudget, freshness - One context packet for a task; see Context packets.
query caps at 4,000 characters, pattern at 2,000, path at 400 (relative, no ..), repository at 200 as owner/name, language at 100. symbol is one plain identifier, and limit runs from 1 to 50.
Refusals
-
403 plan_refusedHobby search_codeandask_code: “Semantic search is included with Pro and Pro+.”-
409 no_repositoriesnothing chosen grep_code,search_codeandask_codebefore any repository is chosen.corpus_statusandlist_repositoriesstill answer200.-
503 index_unavailableretry - The index did not answer, or is waking from rest. Retry;
corpus_statuskeeps answering. -
503 graph_unavailabletrace_code - The index has not written its code graph at the current commit yet. Refresh, then retry.
curl https://usemux.com/api/v1/vaults/01J9Z3K8QF/corpus/query \ -H "Authorization: Bearer $MUX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "organizationId": "org_2Yc81", "operation": "search_code", "arguments": { "query": "retry a failed upload", "repository": "acme/api", "limit": 2 } }'{ "results": [ { "repository": "acme/api", "path": "src/uploads/retry.ts", "line": 14, "endLine": 41, "language": "typescript", "score": 0.82, "excerpt": "export async function retryUpload(job: UploadJob) {\n …", "headSha": "9f3c2a1e4b7d…" } ]}{ "results": [ { "repository": "acme/api", "path": "src/ledger.ts", "line": 88, "endLine": 88, "excerpt": "split(total, accounts)", "headSha": "9f3c2a1e4b7d…" } ], "truncated": false}Get a context packet
POST /v1/vaults/:vaultId/corpus/query
Who can call itviewer
get_context assembles what an agent should read for one task: evidence from the index, the code-graph edges between it, and the findings your workspace has approved, cut to a budget. Every packet has a receiptId you can read back, and propose findings from, for 30 days.
Arguments
-
taskstring required - The task, in words. Up to 4,000 characters.
-
repositoriesstring[] - Up to 20
owner/nameto read from. Defaults to every indexed repository. -
revisionsobject[] - Pin a repository to a commit:
{repository, revision}. -
changedPathsobject[] - Up to 20
{repository, path}your change touches; they are read first. -
tokenBudgetinteger - From 1,024 to 16,000, default 6,000. Counted as UTF-8 bytes, an upper bound for byte-based tokenizers.
-
freshnessstring require_current(default) answers409 context_stalewith the freshness list when an index is behind its branch.allow_staleanswers from the indexed commit and namesstale_or_missing_sourcesinomissions.
Returns
-
evidenceobject[] - Each with
repository,path,line,endLine,headSha,excerpt,score, the file’s gitblob, and areason:literal,semantic,hybrid,changed-pathorgraph:<edge>. -
relationshipsobject[] - Code-graph edges between files in the packet -
imports,tests,calls_route- eachconfidence: "candidate", withtargetRepositoryandtargetRevisionwhen an edge crosses repositories. -
memoriesobject[] - Approved findings that still hold at these commits.
-
omissionsstring[] - What was left out and why:
token_budget,semantic_search_not_in_plan,literal_scan_limit,changed_path_unavailable,graph_unavailable,invalid_or_out_of_scope_evidence,no_evidence. -
freshnessobject[] - Per repository: the expected and indexed revision, and
current,stale,missingorunknown.
curl https://usemux.com/api/v1/vaults/01J9Z3K8QF/corpus/query \ -H "Authorization: Bearer $MUX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "organizationId": "org_2Yc81", "operation": "get_context", "arguments": { "task": "Add rate limiting to the public API", "repositories": ["acme/api"], "tokenBudget": 6000 } }'{ "version": "context-v2", "freshness": [ { "repository": "acme/api", "expectedRevision": "9f3c2a1e4b7d…", "indexedRevision": "9f3c2a1e4b7d…", "state": "current" } ], "evidence": [ { "repository": "acme/api", "path": "src/middleware/auth.ts", "line": 1, "endLine": 60, "headSha": "9f3c2a1e4b7d…", "excerpt": "export const requireKey = …", "score": 0.77, "reason": "hybrid" } ], "relationships": [], "memories": [], "omissions": ["token_budget"], "tokenBudget": 6000, "receiptId": "5b0f6c1e-…", "retrievalMs": 412, "expiresAt": 1729592000000}Propose a finding
POST /v1/vaults/:vaultId/corpus/outcomes
Who can call itagent
A finding is one sentence your agent learned, tied to the commit and files it rests on. Proposed from a context packet’s receipt, it waits for a signed-in owner to approve it with POST /corpus/memories/:memoryId/approve or /retire; a key never can. After each refresh an approved finding moves to the new commit while every file it cites is unchanged, and becomes outdated when one changes.
GET /corpus/memories lists findings: an owner sees all, others their own and the approved ones. GET /corpus/receipts/:receiptId returns a packet to whoever asked for it, and GET /corpus/trace gives a signed-in owner the 25 newest packets and the week’s figures.
Body
-
receiptIdstring required - Your own receipt, unexpired.
-
repositorystring required owner/name.-
revisionstring required - A
headShafrom that receipt. -
statementstring required - The finding, up to 2,000 characters.
-
scopestring personalorworkspace.-
retentionDaysinteger - 1 to 30, default 7.
-
pathsstring[] - 1 to 20 files the receipt read that the finding rests on. Defaults to every file it read there.
curl https://usemux.com/api/v1/vaults/01J9Z3K8QF/corpus/outcomes \ -H "Authorization: Bearer $MUX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "receiptId": "5b0f6c1e-…", "repository": "acme/api", "revision": "9f3c2a1e4b7d…", "statement": "Every public route passes requireKey before its handler.", "scope": "workspace", "paths": ["src/middleware/auth.ts"] }'{ "id": "01J9Z4B2M1", "status": "proposed"}Repositories
Section titled “Repositories”The repositories a workspace indexes come from its GitHub installation. An owner connects GitHub in the browser; after that, editors choose what to index.
List indexed repositories
GET /v1/vaults/:vaultId/repositories
Who can call itviewer
The workspace’s selection with each repository’s index state, the GitHub connection, and the plan’s limit.
Each repository
-
statusstring mirroring,refreshing,fresh,staleorfailed.-
indexedShastring | null - The commit the index was built from.
latestShais the branch’s newest, andstaleis true when they differ. -
files, chunksinteger - What the index holds for it.
-
errorstring | null - Why the last index failed, in words.
curl https://usemux.com/api/v1/vaults/01J9Z3K8QF/repositories \ -H "Authorization: Bearer $MUX_API_KEY"{ "github": { "configured": true, "connected": true, "account": "acme", "installUrl": null }, "canManage": false, "plan": "pro", "limits": { "repositories": 20 }, "refresh": "push", "repositories": [ { "repository": "acme/api", "branch": "main", "status": "fresh", "indexedSha": "9f3c2a1e4b7d…", "latestSha": "9f3c2a1e4b7d…", "stale": false, "indexedAt": 1727000000000, "files": 120, "chunks": 900, "error": null } ]}Choose repositories to index
PUT /v1/vaults/:vaultId/repositories
Who can call iteditor
The body is the whole selection. A repository left out is deselected, and its mirror and index entries are removed. A new one starts as mirroring.
Body
-
repositoriesobject[] required - Each
{repository, branch}.branchdefaults to the repository’s default branch.
Refusals
-
404 repository_not_grantedGitHub - The installation does not grant that repository.
-
403 plan_limitplan - More repositories than the plan indexes: one on Hobby, 20 on Pro, 50 on Pro+.
-
409 github_not_connectedGitHub - Connect GitHub first.
curl -X PUT https://usemux.com/api/v1/vaults/01J9Z3K8QF/repositories \ -H "Authorization: Bearer $MUX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "repositories": [ { "repository": "acme/api", "branch": "main" }, { "repository": "acme/web" } ] }'{ "repositories": [ { "repository": "acme/api", "branch": "main", "status": "fresh", "…": "…" }, { "repository": "acme/web", "branch": "main", "status": "mirroring", "…": "…" } ]}List what GitHub grants
GET /v1/vaults/:vaultId/github/repositories
Who can call iteditor
Every repository the GitHub installation grants, archived ones excluded, marking those already selected. Use it to offer a choice before PUT /repositories.
curl https://usemux.com/api/v1/vaults/01J9Z3K8QF/github/repositories \ -H "Authorization: Bearer $MUX_API_KEY"{ "account": "acme", "repositories": [ { "repository": "acme/api", "defaultBranch": "main", "private": true, "language": "TypeScript", "sizeKb": 1234, "selected": true } ]}Refresh the index
POST /v1/vaults/:vaultId/corpus/refresh
Who can call iteditor
Re-indexes every selected repository, or the one you name. On Pro and Pro+ a push to an indexed branch starts this by itself. A refresh that fails for a moment is tried again after 5, 10 and 20 minutes, on every plan.
Body
-
repositorystring owner/name. Omit it to refresh everything.
Refusals
-
409 refresh_in_progressbusy - A refresh is already running.
-
429 rate_limitedRetry-After: 60 - A refresh was asked for less than a minute ago.
curl https://usemux.com/api/v1/vaults/01J9Z3K8QF/corpus/refresh \ -H "Authorization: Bearer $MUX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "repository": "acme/api" }'{ "started": true}Sandboxes
Section titled “Sandboxes”List sandbox runs
GET /v1/vaults/:vaultId/sandboxes
Who can call itviewer
The workspace’s cloud sandbox tasks and triage runs, most recently active first, with the month’s sandbox hours. A run silent for 30 minutes reads as asleep; live counts only the running ones.
The helios-sandbox Worker records what it runs with PUT /v1/vaults/:vaultId/sandboxes/:id; who ran it is read from the credential, never the body.
Before a sandbox starts or wakes, the Worker asks POST /v1/vaults/:vaultId/sandboxes/:id/admit. Sandbox hours, sandboxes awake at once, Triage tokens and Jev are counted per person: in a team each member spends their own plan’s allowance, wherever they spend it. A start past a cap answers 402 with the cap body below; sentence is what to show the reader, and nextPlan is the plan to offer, or null on Pro+.
{ "error": "cap", "meter": "sandboxHours", "plan": "pro", "nextPlan": "proplus", "resetsAt": 1727740800000, "sentence": "You've used this month's 30 sandbox-hours. Pro+ has 300, 8 sandboxes at once and $10 of Jev. Upgrade or wait for 1 October."}Query parameters
-
limitinteger - 1 to 100, default 50.
-
beforestring - The
nextcursor from the previous page. -
includedeleted - Include deleted runs.
curl "https://usemux.com/api/v1/vaults/01J9Z3K8QF/sandboxes?limit=1" \ -H "Authorization: Bearer $MUX_API_KEY"{ "sandboxes": [ { "id": "3d0c1f7a-…", "kind": "task", "state": "asleep", "startedBy": { "id": "usr_7Qb", "name": "Ada" }, "deviceName": "Ada's MacBook Pro", "startedAt": 1727000000000, "lastActiveAt": 1727003600000, "endedAt": null, "checkpoints": 2 } ], "live": 0, "next": "1727000000000.3d0c1f7a-…", "usage": { "hoursUsed": 3.2, "hoursAllowed": 30, "runningPerMember": 2, "resetsAt": 1727740800000, "warning": null }}Device sign-in
Section titled “Device sign-in”A Mac signs itself in rather than holding a pasted key: it asks for a code, the person approves it in the browser, and the device collects a key of its own. muxcode does this for you; build it the same way for any client.
Start a device sign-in
POST /v1/connect
Who can call itnone; limited by address
Returns a code for the person to confirm at verificationUrl. Codes last ten minutes. The browser’s half is GET /v1/connect/requests/:userCode and its approve and deny, for a signed-in person.
Body
-
deviceNamestring required - What the person will see, up to 80 characters.
-
clientstring required muxcode.-
clientVersionstring - Up to 40 characters.
-
deviceProofobject { uuidHash, keychainToken? }:uuidHashis the SHA-256 hex of the Mac’s hardware UUID, hashed on the device;keychainTokenis the token a trial’s first sign-in returned. A Mac that sends it may start a 72-hour trial of Pro, once per device, keychain, inbox and person.
curl https://usemux.com/api/v1/connect \ -H "Content-Type: application/json" \ -d '{ "deviceName": "Ada’s MacBook Pro", "client": "muxcode" }'{ "deviceCode": "q3V9…", "userCode": "KQRT-7M2P", "verificationUrl": "https://usemux.com/app/connect?code=KQRT-7M2P", "expiresAt": 1727000600, "interval": 3}Poll for the key
POST /v1/connect/poll
Who can call itthe device code
Poll at the returned interval until the person approves. The answer is a bare status: 202 pending, 429 slow_down when polled too soon, 410 denied, spent or expired. Once approved it carries the device’s own key; a code cannot be collected twice.
Beside the plan, the approved answer carries trial and meters. trial is null, or { startedAt, endsAt, jevMicroUsd, sandboxSeconds, outcome, reason? } with outcome one of live, ended, upgraded or refused; keychainToken is in it only on the answer that started the trial, or gave the Mac that started it a new one. Keep it in the keychain and send it back in deviceProof. meters is where the person stands against the caps they are held to; pooled is true in a team.
A cap body refused during a trial names plan as trial.
A device signs itself out with DELETE /v1/connect/device. An owner or admin signs out any device with DELETE /v1/organizations/:orgId/devices/:keyId.
Body
-
deviceCodestring required - From the start.
curl https://usemux.com/api/v1/connect/poll \ -H "Content-Type: application/json" \ -d '{ "deviceCode": "q3V9…" }'{ "status": "approved", "baseUrl": "https://usemux.com/api", "organizationId": "org_2Yc81", "corpusId": "01J9Z3K8QG", "key": "hk_live_01J9Z4C7T3…", "workspaceName": "Acme", "corpusName": "Code corpus", "plan": "pro", "role": "editor", "trial": { "startedAt": 1727000000000, "endsAt": 1727259200000, "keychainToken": "c2Vj…", "jevMicroUsd": 0, "sandboxSeconds": 0, "outcome": "live" }, "meters": { "sandboxHoursUsed": 0, "sandboxHoursCap": 3, "sandboxesAwake": 0, "sandboxesCap": 1, "jevMicroUsdUsed": 0, "jevMicroUsdCap": 1000000, "resetsAt": 1727259200000, "pooled": false }}Start a trial from a signed-in Mac
POST /v1/connect/trial
Who can call itthe device's own key
A Mac already signed in asks for its trial without a second sign-in in the browser. Only a device’s key may ask, not one made by hand. The rules are the sign-in’s: once per device, keychain, inbox and person. The answer is { plan, trial, meters } in the poll’s shapes; trial.keychainToken is in it only when this call started the trial or gave the Mac that started it a new one.
Body
-
deviceProofobject required { uuidHash, keychainToken? }, as sent toPOST /v1/connect.
Mint a key
POST /v1/vaults/:vaultId/keys
Who can call itowner, signed-in person
Mints a workspace key. The key is in this answer only. GET /keys lists the workspace’s keys, revoked ones included, and DELETE /keys/:id revokes one; both also need a signed-in owner.
Body
-
rolestring required viewer,agent,editororowner.-
principalTypestring required agentfor a program,humanfor a person’s own tool.-
agentNamestring - Required for an agent key: what it is, up to 100 characters.
-
expiresAtinteger - When it stops working, in milliseconds. Keys do not expire by default.
curl https://usemux.com/api/v1/vaults/01J9Z3K8QF/keys \ -H "Cookie: $SESSION_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "role": "agent", "principalType": "agent", "agentName": "ci-bot" }'{ "id": "01J9Z4D1K8", "key": "hk_live_01J9Z4D1K9…", "role": "agent", "principalType": "agent", "agentName": "ci-bot", "expiresAt": null, "createdAt": 1727000000000}Billing
Section titled “Billing”Retrieve billing
GET /v1/billing
Who can call itany key or member
The organization’s plan, its limits and this month’s usage. GET /v1/billing/plan returns only {plan}. Changing a plan or the billing contact happens in the app, for the organization’s billing owner.
curl https://usemux.com/api/v1/billing \ -H "Authorization: Bearer $MUX_API_KEY"{ "orgId": "org_2Yc81", "plan": "pro", "status": "active", "currentPeriodEnds": 1729592000000, "pendingPlan": null, "cancelAtPeriodEnd": false, "canManage": false, "limits": { "vaults": 1, "apiCallsPerMin": 120, "apiCallsPerMonth": 500000, "semantic": true, "indexedRepositories": 20, "indexRefresh": "push" }, "usage": { "vaults": 1, "indexedRepositories": 2, "apiCalls": 1234 }}Ask Jev
POST /v1/jev/systemone
Who can call ita person's key, or a sandbox task token
Jev, the classifier, through mux. The body goes to TypeSafe’s System One as sent, and its answer comes back as it came: status, body and content type. Before the call is sent it is charged to the person’s Jev allowance ($1 a month on Pro, $10 on Pro+, $1 over a trial) at $0.042 a million input tokens, four bytes of body to a token, rounded up to a whole millionth of a dollar. Once the allowance is spent the call is not sent and the answer is 402 with the cap body, meter jev. Hobby answers 402 plan_refused. A call that TypeSafe fails or that takes longer than 15 seconds (504) stays charged. Where mux holds no Jev key the answer is 503 and nothing is charged.
curl https://usemux.com/api/v1/jev/systemone \ -H "Authorization: Bearer $MUX_API_KEY" \ -H "Content-Type: application/json" \ -d @questions.jsonReport a Jev call
POST /v1/jev/usage
Who can call ita person's key
muxcode reports each call it made to Jev on its own key, and is told where the person stands against the month’s Jev allowance. A call is priced as POST /v1/jev/systemone prices it, and is counted even past the cap, since it was already made; a call sent through systemone is charged there and is not reported again. inputBytes of 0 charges nothing and only asks where the person stands. Hobby records nothing: Jev runs on the person’s own keys there. refusal is the cap body once over is true.
Body
-
inputBytesinteger required - The bytes sent to the classifier, or
0to ask without charging.
{ "jevMicroUsdUsed": 42000, "jevMicroUsdCap": 1000000, "over": false, "refusal": null}Tell us what you're building
POST /v1/feedback
Who can call ita person on Pro+
A Pro+ reader at a cap writes to hello@usemux.com. Any other plan answers 403.
Body
-
textstring required - What they are building, up to 5,000 characters.
-
meterstring - The meter they hit:
sandboxHours,sandboxesAwakeorjev.
{ "accepted": true }Routes for the app
Section titled “Routes for the app”The web app manages workspaces, people, GitHub and billing through these routes. They need a signed-in person unless noted, and are listed so every route is accounted for.
| Method | Path | Who | Purpose |
|---|---|---|---|
POST |
/v1/workspaces |
person | Create an organization and its first workspace |
POST |
/v1/vaults |
org owner | Create a workspace; body: name |
PATCH |
/v1/vaults/:vaultId |
owner | Rename a workspace |
DELETE |
/v1/vaults/:vaultId |
owner | Delete a workspace; kept for 30 days |
POST |
/v1/vaults/:vaultId/restore |
org owner | Restore a deleted workspace within 30 days |
GET |
/v1/vaults/:vaultId/grants |
owner | Who can reach the workspace |
POST |
/v1/vaults/:vaultId/grants |
owner | Grant a member access; body: email, role |
DELETE |
/v1/vaults/:vaultId/grants/:principalId |
owner | Revoke a grant |
GET |
/v1/vaults/:vaultId/analytics |
viewer | Home’s charts; days: 7, 30 or 90 |
GET |
/v1/organizations/:orgId/members |
member | Members, pending invitations, signed-in Macs |
POST |
/v1/organizations/:orgId/invitations |
owner or admin | Invite a person; body: email, role |
DELETE |
/v1/organizations/:orgId/invitations/:id |
owner or admin | Cancel an invitation |
DELETE |
/v1/organizations/:orgId/devices/:keyId |
member (own) or admin | Sign a device out |
GET |
/v1/organizations/:orgId/github |
org owner | GitHub connection state |
POST |
/v1/organizations/:orgId/github/install |
org owner | Start the GitHub App installation, or link one with {"link":true} |
POST |
/v1/organizations/:orgId/github |
org owner | Finish the installation from GitHub’s callback |
DELETE |
/v1/organizations/:orgId/github |
org owner | Disconnect GitHub and drop its selections |
POST |
/v1/billing/checkout |
billing owner | Start a checkout; body: plan |
GET |
/v1/billing/checkout/:checkoutId |
billing owner | Confirm a checkout return |
POST |
/v1/billing/change-plan |
billing owner | Change a paid plan |
POST |
/v1/billing/keep-plan |
billing owner | Drop a scheduled plan change |
POST |
/v1/billing/transfer-owner |
billing owner | Hand billing to another member |
POST |
/v1/billing/cancel |
billing owner | Cancel at the period’s end |
POST |
/v1/billing/reactivate |
billing owner | Undo a pending cancellation |
POST |
/v1/billing/portal |
billing owner | Open the billing portal |
POST |
/v1/billing/webhook |
Polar signature | Billing events |
POST |
/v1/webhooks/github-app |
GitHub signature | Push and installation events; a push to an indexed branch marks it stale |