Accept alignment suggestions
Accepts one or more suggestions, creating a tracked alignment prompt from each. A suggestion whose text already matches an active alignment prompt — either one already live on the brand, or another suggestion in the same batch — is linked to that prompt instead of creating a duplicate.
A suggestion proposing a brand-new category (proposed_category_name/proposed_category_slug)
materializes that category the first time a suggestion using its slug is accepted. If a category
with that slug already exists by then, the existing one is reused rather than duplicated or
overwritten.
This is a billable action: each newly-created prompt consumes an alignment-prompt slot per market it targets (minimum 1). The check runs against the whole batch before anything is written — if the batch would not fit your remaining allowance, nothing in it is created. Category creation itself never consumes quota.
Bulk-shaped only. There is no single-suggestion accept endpoint; send one id for the single-row case.
Requires the write:alignment scope, and the workspace must be enabled for API writes.
POST /v1/brands/{brand_id}/alignment/suggestions/acceptAuthorization
| Header | Type | Required |
|---|---|---|
Authorization | Bearer asky_sk_… | required |
Idempotency-Key | string | required |
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
brand_id | uuid | required | From List brands |
Body
application/json
| Field | Type | Required | Description |
|---|---|---|---|
suggestion_ids | uuid[], 1-200 | required | From List alignment suggestions |
Request
cURL
curl --request POST \
--url 'https://api.askylabs.com/v1/brands/242546de-4cee-4a7d-952e-f6aa60c63ef8/alignment/suggestions/accept' \
--header 'Authorization: Bearer <api-key>' \
--header 'Idempotency-Key: 5b0e77d2-13a9-4f6a-8ce1-9a3f5e21c0aa' \
--header 'Content-Type: application/json' \
--data '{"suggestion_ids": ["e4a2c8f0-6b1d-4a9e-9c3f-1d8b5a2e7f60"]}'Response
200
{
"data": {
"promoted": [
{
"suggestion_id": "e4a2c8f0-6b1d-4a9e-9c3f-1d8b5a2e7f60",
"prompt_id": "c91f6a3e-4d28-4b16-9a8c-5c0f7e2d1a93",
"deduped": false
}
],
"already_promoted": [],
"quota": {
"limit": 100,
"used": 64,
"remaining": 36
}
},
"request_id": "req_5b0e77d213a94f6a8ce1"
}Response fields
| Field | Type | Description |
|---|---|---|
data.promoted[].suggestion_id | uuid | required |
data.promoted[].prompt_id | uuid | required. Find it via List alignment prompts |
data.promoted[].deduped | boolean | required. true if this linked to a pre-existing (or same-batch) prompt instead of creating one |
data.already_promoted[].suggestion_id | uuid | required. Ids that were already decided before this call — a no-op |
data.already_promoted[].prompt_id | uuid | null | required |
data.quota | object | Present only when at least one new prompt was created |
data.quota.limit | integer | null | Your plan’s alignment-prompt limit, null if unlimited |
data.quota.used | integer | Including this batch |
data.quota.remaining | integer | What is left after this call |
request_id | string | required. Also returned as the x-request-id header. Quote it when contacting support |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_request | suggestion_ids is empty, over 200 entries, contains an id not found for this brand, or contains an id whose status is not proposed (and not already accepted/promoted) |
| 401 | invalid_token | The key is missing, malformed, or does not exist |
| 401 | token_expired | The key passed its expiry date |
| 401 | token_revoked | The key was revoked |
| 403 | insufficient_scope | The key does not carry write:alignment |
| 403 | plan_required | This workspace is not enabled for API writes |
| 403 | quota_exceeded | The batch would exceed your alignment-prompt allowance. Nothing is created |
| 404 | not_found | The brand does not exist, or this key is not allowed to reach it |
| 429 | rate_limited | Over 60 requests per minute |
| 503 | service_unavailable | Your allowance could not be checked. Nothing is created. Retry shortly |
Notes
Validation is all-or-nothing. An id that is missing, belongs to another brand, or has already
been rejected refuses the entire call and names every offender — unlike the app’s own bulk
accept, which reports per-row failures under a 200. Retry with the bad ids removed.
Replaying an already-accepted id is safe. If a suggestion was already promoted or accepted
(by an earlier call, or by a human in the app) it comes back in already_promoted rather than
causing an error — this endpoint is safe to retry after a timeout.
deduped: true means no new prompt was created. It fires two ways: the suggestion’s text
already matched an active alignment prompt on the brand, or another suggestion earlier in this same
batch normalized to the same text. Either way it is linked to that prompt rather than creating a
duplicate. Deduped rows do not consume quota and are not included in data.quota.
A proposed category materializes at most once per slug, per call. Accepting several
suggestions that propose the same new category (same proposed_category_slug) creates that
category only once and links every one of them to it.
Idempotency-Key matters more here than elsewhere. Reuse it when retrying and the original
response is replayed rather than a second batch being processed. See
Idempotency.