Skip to content

Dismiss a proposed analysis, or send it to the wizard

POST
/api/agents/intake/{id}/close/
curl --request POST \
--url http://localhost:8000/api/agents/intake/example/close/ \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "outcome": "edited" }'

Dismiss a proposed analysis, or record that the coach took it to the upload wizard instead (issue #1689).

Costs nothing either way. outcome distinguishes the two, and the difference is a pilot metric rather than a detail: edited means the agent read the clip wrong and a human corrected it, declined means the coach did not want the analysis.

Only a still-open proposal can be closed — 400 intake_closed otherwise, because closing a confirmed intake would orphan an analysis that is already running and already paid for.

id
required
string

Body of POST /api/agents/intake/<id>/close/.

One endpoint for two outcomes because they are one transition with two meanings, and the difference is the pilot’s whole manual-intervention number: edited says the agent read the clip wrong and the coach took it to the wizard, declined says they did not want the analysis at all. Splitting them into two routes would make that distinction a URL rather than data, and the funnel would have to reconstruct it from which path was hit.

object
outcome
required
  • declined - declined
  • edited - edited
string
Allowed values: declined edited

Examples

ExampleTakenToTheWizard

Taken to the wizard

{
"outcome": "edited"
}
Media typeapplication/json

Body of the intake confirm / close responses.

card is the SAME payload the conversation persisted, rebuilt from the updated row — so the client swaps the card it is showing for this one rather than patching a status into a payload it holds, and the two cannot drift.

object
intake_id
required
string
status
required
string
session_id
required
string
nullable
card
required
object
key
additional properties

Example generated

{
"intake_id": "example",
"status": "example",
"session_id": "example",
"card": {
"additionalProperty": "example"
}
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string

Example generated

{
"detail": "example"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string

Example generated

{
"detail": "example"
}

The caller’s tier does not include the coaching agents.

Media typeapplication/json
object
detail
required

One of eight canonical strings. The front-end paywall switches copy + CTA on this value (exact string equality — do not localise). quota_exhausted / seat_limit_reached / client_limit_reached / feature_not_in_plan lead to an upgrade CTA; subscription_suspended leads to a Billing Portal CTA so the buyer can update their payment method; exercise_not_in_plan leads to a contact-us CTA — the movement list is sales-managed, no tier adds to it (#2030). trial_expired / access_ended mean the team is read-only (#2901): everything opens, nothing new is created; they lead to a subscribe CTA and always carry reset_at: null.

  • quota_exhausted - Session quota for the period reached 0
  • subscription_suspended - Stripe dunning in flight (past_due / unpaid)
  • seat_limit_reached - Adding another team member would exceed plan.max_seats
  • client_limit_reached - Adding another Client would exceed plan.max_client_profiles
  • feature_not_in_plan - The tier does not include this whole feature surface
  • exercise_not_in_plan - The (activity, exercise) is not in the team’s exercise grants
  • trial_expired - The team is read-only: its self-serve trial ended
  • access_ended - The team is read-only: its paid plan or granted access ended
string
Allowed values: quota_exhausted subscription_suspended seat_limit_reached client_limit_reached feature_not_in_plan exercise_not_in_plan trial_expired access_ended
reset_at
required

ISO-8601 UTC timestamp the team’s current period ends. Null when the team has no live subscription (legacy un-migrated row). On Free + paid this is the renewal moment; quota refreshes to exactly plan.session_quota (NOT additive — leftover sessions don’t roll over).

string format: date-time
nullable
current_plan
required

The active plan’s role string (free, starter, professional, organization, strategic). Same value as current_role — kept as two separate fields for forward-compatibility with a future named-plan split where current_plan could carry an SKU and current_role the tier label.

string
current_role
required

The active plan’s role string. See current_plan.

string
feature

Which feature surface is locked. Present ONLY on feature_not_in_plan, so one modal can name what’s gated without a detail string per feature (#773). The only value today is agents (aikynetix/agents/services.py::AGENTS_FEATURE).

string

Examples

Example402—AgentsNotInPlan

Free team opens an agent conversation

{
"detail": "feature_not_in_plan",
"reset_at": null,
"current_plan": "free",
"current_role": "free",
"feature": "agents"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string

Example generated

{
"detail": "example"
}

No such intake for this coach, or the intake capability is off for this deployment.

Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string

Example generated

{
"detail": "example"
}
Media typeapplication/json
object
detail
required

429 — rate limit exceeded. Honour the Retry-After response header (seconds to wait) before retrying; it is sent on every 429.

string

Example generated

{
"detail": "example"
}