Set or clear the authored chat-with-app starter prompt
Owner-only. When non-null, the authored text leads the prompt body for the “Open in Claude / Open in ChatGPT / Copy prompt” control-panel actions, and the app’s name, description, URL (and, for unclaimed apps, an access token) are appended automatically at render time. Write a generic getting-started instruction — do NOT embed the app’s URL, or every remixer’s deeplink would point at the template instead of their own copy. Pass null (or an empty string) to clear and revert to the generic default. Idempotent: a repeated call with the same value is a no-op.
PUT
/app/{id}/starter-promptAuthorization
AuthorizationBearer token (bld_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
idstringrequiredRequest body
requiredapplication/jsonstarter_promptstring | nullrequiredPrompt body prefilled in the chat host when a visitor clicks "Open in Claude" / "Open in ChatGPT". Max 2000 characters. Pass `null` or `""` to clear.
max length 2000
Responses
200Starter prompt updated.
starter_promptstring | nullrequired400Body is malformed or the prompt exceeds the length cap.
okbooleanrequiredAllowed:
falseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
Allowed:
not_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_invitedmessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. `token_revoked_post_claim` is the post-#1284 surface for a bld_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 | RecoveryRenameSelf-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 `version_mismatch` / `invalid_if_match` / 428 `precondition_required`, `fix_route_label` for 403 `forbidden_write`, `open_existing` for 409 `duplicate_remix`, and `rename` for 409 `manifest_id_immutable` / `manifest_id_conflict`. 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:
renameinstructionsstringrequired401User-scoped auth required.
okbooleanrequiredAllowed:
falseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
Allowed:
not_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_invitedmessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. `token_revoked_post_claim` is the post-#1284 surface for a bld_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 | RecoveryRenameSelf-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 `version_mismatch` / `invalid_if_match` / 428 `precondition_required`, `fix_route_label` for 403 `forbidden_write`, `open_existing` for 409 `duplicate_remix`, and `rename` for 409 `manifest_id_immutable` / `manifest_id_conflict`. 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:
renameinstructionsstringrequired403Caller does not own this app, or the app is anon-owned.
okbooleanrequiredAllowed:
falseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
Allowed:
not_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_invitedmessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. `token_revoked_post_claim` is the post-#1284 surface for a bld_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 | RecoveryRenameSelf-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 `version_mismatch` / `invalid_if_match` / 428 `precondition_required`, `fix_route_label` for 403 `forbidden_write`, `open_existing` for 409 `duplicate_remix`, and `rename` for 409 `manifest_id_immutable` / `manifest_id_conflict`. 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:
renameinstructionsstringrequired404App not found.
okbooleanrequiredAllowed:
falseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
Allowed:
not_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_invitedmessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. `token_revoked_post_claim` is the post-#1284 surface for a bld_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 | RecoveryRenameSelf-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 `version_mismatch` / `invalid_if_match` / 428 `precondition_required`, `fix_route_label` for 403 `forbidden_write`, `open_existing` for 409 `duplicate_remix`, and `rename` for 409 `manifest_id_immutable` / `manifest_id_conflict`. 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:
renameinstructionsstringrequiredRequest
curl -X PUT "https://charm.ing/app/string/starter-prompt" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"starter_prompt": "string"
}'const response = await fetch("https://charm.ing/app/string/starter-prompt", {
method: "PUT",
headers: {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
"starter_prompt": "string"
})
});import requests
response = requests.put(
"https://charm.ing/app/string/starter-prompt",
headers={
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
json={
"starter_prompt": "string"
},
)Response
{
"starter_prompt": "string"
}{
"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"
}
}
}{
"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"
}
}
}