Read an app build and its accepted source
Read progress or the retained terminal result using current user source access. Set include_source=true to inspect the exact accepted input. Only published means the app is live. Status remains available after authoring cohort removal. Accept: text/html renders progress and terminal results; pending pages refresh this status resource and published pages redirect to the actual app URL.
GET
/api/v1/app-builds/{buildId}Authorization
AuthorizationBearer token (chrm_user_*) · headerrequiredUser-scoped personal access token. Mint via `POST /api/token` after signing in, or via the device-pairing flow at `POST /api/pair/start`. Authorises everything the user can do.
Path parameters
buildIdstringrequiredQuery parameters
include_sourcebooleanResponses
200Current build operation.
okbooleanrequiredAllowed:
truebuildIdstringrequiredintentstringrequiredAllowed:
createupdatemigraterestorecopystatestringrequiredAllowed:
queuedresolvingbuildingvalidatingpublishedfailedsupersededcanceledexpiredsourceEtagstringrequiredstatusUrlstring<uri>requiredretryAfterSecondsintegerappIdstring<uuid>revisionintegerPublished app source revision. Present only after successful publication.
min 1
desiredRevisionintegeractiveRevisionintegerurlstring<uri>attemptsintegerrequiredacceptedAtstring<date-time>requiredupdatedAtstring<date-time>requiredfinishedAtstring<date-time> | nullrequiredelapsedMsintegerrequiredlockStatestringrequiredAllowed:
lockedunresolvedinputDigeststringrequiredlockDigeststringresolvedDependenciesobjectShow propertiesHide properties
serverobjectrequiredclientobjectrequiredqueueDeadlinestring<date-time>requireddeadlinestring<date-time>requiredinspectionExpiresAtstring<date-time> | nullrequiredidempotencyExpiresAtstring<date-time> | nullrequiredsourceobjectShow propertiesHide properties
modulestringrequireduistring | nullrequiredstylesstring | nullrequireddescriptionstring | nullrequirederrorobjectShow propertiesHide properties
kindstringrequiredmessagestringrequiredretryablebooleanrequiredtargetstringspecifierstringlineintegercolumninteger303Browser navigation to the actual published app URL.
400Invalid source inclusion query.
okbooleanrequiredAllowed:
falseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
Allowed:
not_foundunknown_operationoperation_not_foundoperation_failedunauthorizedsign_in_requiredtoken_expiredforbiddenforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedduplicate_remixmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takenapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. `token_revoked_post_claim` is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the `recovery` field on the same `error` object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
Allowed:
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimrecoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryOpenExisting | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on `kind`. Attached to error envelopes the agent can self-correct on: `pair` for `token_revoked_post_claim` 401s (#1284), `retry` for 429s, `shrink` for too-large / quota-exceeded 413s, `refetch` for 412 `revision_mismatch` / `invalid_if_match` / 428 `precondition_required`, `fix_route_label` for 403 `forbidden_write`, `open_existing` for 409 `duplicate_remix`, `rename` for 409 `manifest_id_immutable` / `manifest_id_conflict`, and `migrate_contract` for 422 `contract_migration_required`. Every `instructions` string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
One of:
RecoveryPair
kindstringrequiredAllowed:
pairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredRecoveryRetry
kindstringrequiredAllowed:
retryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the `RateLimit-Reset` and `Retry-After` headers on the same response.
min 0
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredRecoveryShrink
kindstringrequiredAllowed:
shrinkfieldstringrequiredWhich input tripped the cap.
Allowed:
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredmin 0
cap_bytesintegerrequiredmin 0
instructionsstringrequiredRecoveryRefetch
kindstringrequiredAllowed:
refetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredRecoveryFixRouteLabel
kindstringrequiredAllowed:
fix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
RecoveryOpenExisting
kindstringrequiredAllowed:
open_existingexisting_app_idstringrequiredexisting_urlstring<uri>requiredinstructionsstringrequiredRecoveryRename
kindstringrequiredAllowed:
renameinstructionsstringrequiredRecoveryMigrateContract
kindstringrequiredAllowed:
migrate_contractinstructionsstringrequired401User authentication required.
okbooleanrequiredAllowed:
falseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
Allowed:
not_foundunknown_operationoperation_not_foundoperation_failedunauthorizedsign_in_requiredtoken_expiredforbiddenforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedduplicate_remixmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takenapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. `token_revoked_post_claim` is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the `recovery` field on the same `error` object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
Allowed:
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimrecoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryOpenExisting | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on `kind`. Attached to error envelopes the agent can self-correct on: `pair` for `token_revoked_post_claim` 401s (#1284), `retry` for 429s, `shrink` for too-large / quota-exceeded 413s, `refetch` for 412 `revision_mismatch` / `invalid_if_match` / 428 `precondition_required`, `fix_route_label` for 403 `forbidden_write`, `open_existing` for 409 `duplicate_remix`, `rename` for 409 `manifest_id_immutable` / `manifest_id_conflict`, and `migrate_contract` for 422 `contract_migration_required`. Every `instructions` string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
One of:
RecoveryPair
kindstringrequiredAllowed:
pairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredRecoveryRetry
kindstringrequiredAllowed:
retryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the `RateLimit-Reset` and `Retry-After` headers on the same response.
min 0
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredRecoveryShrink
kindstringrequiredAllowed:
shrinkfieldstringrequiredWhich input tripped the cap.
Allowed:
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredmin 0
cap_bytesintegerrequiredmin 0
instructionsstringrequiredRecoveryRefetch
kindstringrequiredAllowed:
refetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredRecoveryFixRouteLabel
kindstringrequiredAllowed:
fix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
RecoveryOpenExisting
kindstringrequiredAllowed:
open_existingexisting_app_idstringrequiredexisting_urlstring<uri>requiredinstructionsstringrequiredRecoveryRename
kindstringrequiredAllowed:
renameinstructionsstringrequiredRecoveryMigrateContract
kindstringrequiredAllowed:
migrate_contractinstructionsstringrequired404Build not found or inaccessible.
okbooleanrequiredAllowed:
falseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
Allowed:
not_foundunknown_operationoperation_not_foundoperation_failedunauthorizedsign_in_requiredtoken_expiredforbiddenforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedduplicate_remixmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takenapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. `token_revoked_post_claim` is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the `recovery` field on the same `error` object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
Allowed:
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimrecoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryOpenExisting | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on `kind`. Attached to error envelopes the agent can self-correct on: `pair` for `token_revoked_post_claim` 401s (#1284), `retry` for 429s, `shrink` for too-large / quota-exceeded 413s, `refetch` for 412 `revision_mismatch` / `invalid_if_match` / 428 `precondition_required`, `fix_route_label` for 403 `forbidden_write`, `open_existing` for 409 `duplicate_remix`, `rename` for 409 `manifest_id_immutable` / `manifest_id_conflict`, and `migrate_contract` for 422 `contract_migration_required`. Every `instructions` string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
One of:
RecoveryPair
kindstringrequiredAllowed:
pairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredRecoveryRetry
kindstringrequiredAllowed:
retryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the `RateLimit-Reset` and `Retry-After` headers on the same response.
min 0
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredRecoveryShrink
kindstringrequiredAllowed:
shrinkfieldstringrequiredWhich input tripped the cap.
Allowed:
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredmin 0
cap_bytesintegerrequiredmin 0
instructionsstringrequiredRecoveryRefetch
kindstringrequiredAllowed:
refetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredRecoveryFixRouteLabel
kindstringrequiredAllowed:
fix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
RecoveryOpenExisting
kindstringrequiredAllowed:
open_existingexisting_app_idstringrequiredexisting_urlstring<uri>requiredinstructionsstringrequiredRecoveryRename
kindstringrequiredAllowed:
renameinstructionsstringrequiredRecoveryMigrateContract
kindstringrequiredAllowed:
migrate_contractinstructionsstringrequiredTry it
Server
Authorization
Parameters
Request
curl -X GET "https://charm.ing/api/v1/app-builds/string" \
-H "Authorization: Bearer YOUR_TOKEN"const response = await fetch("https://charm.ing/api/v1/app-builds/string", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_TOKEN"
}
});import requests
response = requests.get(
"https://charm.ing/api/v1/app-builds/string",
headers={
"Authorization": "Bearer YOUR_TOKEN"
},
)Response
{
"ok": true,
"buildId": "string",
"intent": "create",
"state": "queued",
"sourceEtag": "string",
"statusUrl": "http://example.com",
"retryAfterSeconds": 0,
"appId": "28c365d5-df94-4a54-8217-3ce51d068868",
"revision": 1,
"desiredRevision": 0,
"activeRevision": 0,
"url": "http://example.com",
"attempts": 0,
"acceptedAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"finishedAt": "2019-08-24T14:15:22Z",
"elapsedMs": 0,
"lockState": "locked",
"inputDigest": "string",
"lockDigest": "string",
"resolvedDependencies": {
"server": {
"property1": "string",
"property2": "string"
},
"client": {
"property1": "string",
"property2": "string"
}
},
"queueDeadline": "2019-08-24T14:15:22Z",
"deadline": "2019-08-24T14:15:22Z",
"inspectionExpiresAt": "2019-08-24T14:15:22Z",
"idempotencyExpiresAt": "2019-08-24T14:15:22Z",
"source": {
"module": "string",
"ui": "string",
"styles": "string",
"description": "string"
},
"error": {
"kind": "string",
"message": "string",
"retryable": true,
"target": "string",
"specifier": "string",
"line": 0,
"column": 0
}
}Browser navigation to the actual published app URL.
{
"ok": false,
"error": {
"kind": "not_found",
"message": "string",
"reason": "token_malformed",
"recovery": {
"kind": "pair",
"start": "http://example.com",
"verification_url": "http://example.com",
"instructions": "string"
}
}
}{
"ok": false,
"error": {
"kind": "not_found",
"message": "string",
"reason": "token_malformed",
"recovery": {
"kind": "pair",
"start": "http://example.com",
"verification_url": "http://example.com",
"instructions": "string"
}
}
}{
"ok": false,
"error": {
"kind": "not_found",
"message": "string",
"reason": "token_malformed",
"recovery": {
"kind": "pair",
"start": "http://example.com",
"verification_url": "http://example.com",
"instructions": "string"
}
}
}