Canonical per-app agent descriptor (side-effect-free)
Side-effect-free sibling of the page gate: no auto-claim, no token mint, no cookie, no mutating telemetry. A public or remixable app returns the full descriptor to anyone, with operations[].input/output/examples gated on app:read (owner, accepted share grant, team membership, or a bearer token) — an anonymous caller sees discovery-level operation fields only. A private app returns the full descriptor only to a caller who already holds app:read; everyone else — including an unclaimed app’s claim-cookie holder, which grants app:run but never app:read — gets the minimal stub (AppDescriptorStub). Reachable via both the /app/{id} UUID form and the /{handle}/{app-name} friendly form (byte-identical id + canonical_url), and advertised from the served page’s <link rel="alternate" type="application/json"> and matching Link: HTTP header.
/app/{id}/agent.jsonOptional — this operation also accepts unauthenticated requests.
AuthorizationBearer token (bld_app_*) · headerAuthorizationBearer token (bld_user_*) · headeridstringrequiredobjectokbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequirednot_foundunknown_operationoperation_not_foundoperation_failedunauthorizedtoken_expiredforbiddenforbidden_writestorage_quota_exceededinvalid_moduleinvalid_uiinvalid_route_schemainvalid_routes_shapeinvalid_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_limitedtoo_many_requestsexpiredalready_approvedanon_not_remixableinvalid_if_matchprecondition_requiredversion_mismatchold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existsinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedread_onlyhandle_takeninvalid_handlename_takenapp_unclaimedlink_cap_reachedgrantee_is_owneralready_invitedmessagestringreasonstringtoken_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimrecoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryOpenExisting | RecoveryRenameShow propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredretry_after_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredmoduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredkindstringrequiredopen_existingexisting_app_idstringrequiredexisting_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredrenameinstructionsstringrequiredokbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequirednot_foundunknown_operationoperation_not_foundoperation_failedunauthorizedtoken_expiredforbiddenforbidden_writestorage_quota_exceededinvalid_moduleinvalid_uiinvalid_route_schemainvalid_routes_shapeinvalid_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_limitedtoo_many_requestsexpiredalready_approvedanon_not_remixableinvalid_if_matchprecondition_requiredversion_mismatchold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existsinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedread_onlyhandle_takeninvalid_handlename_takenapp_unclaimedlink_cap_reachedgrantee_is_owneralready_invitedmessagestringreasonstringtoken_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimrecoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryOpenExisting | RecoveryRenameShow propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredretry_after_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredmoduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredkindstringrequiredopen_existingexisting_app_idstringrequiredexisting_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredrenameinstructionsstringrequiredcurl -X GET "https://charm.ing/app/string/agent.json" \
-H "Authorization: Bearer YOUR_TOKEN"const response = await fetch("https://charm.ing/app/string/agent.json", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_TOKEN"
}
});import requests
response = requests.get(
"https://charm.ing/app/string/agent.json",
headers={
"Authorization": "Bearer YOUR_TOKEN"
},
){}{
"ok": false,
"error": {
"kind": "not_found",
"message": "string",
"reason": "token_malformed",
"recovery": {
"kind": "pair",
"start": "<uri>",
"verification_url": "<uri>",
"instructions": "string"
}
}
}{
"ok": false,
"error": {
"kind": "not_found",
"message": "string",
"reason": "token_malformed",
"recovery": {
"kind": "pair",
"start": "<uri>",
"verification_url": "<uri>",
"instructions": "string"
}
}
}