AurionAI Docs

CSAT Surveys

Configure and manage customer satisfaction surveys via the Aurion API.

⚠️ Preview — not yet in the public API

The endpoints on this page are part of the AurionAI helpdesk and are currently accessible only through an authenticated dashboard session. They are not yet exposed through public API keys — a request authenticated with X-API-Key returns 403. Public API-key access is planned. The reference below documents the intended contract.

CSAT Surveys

The CSAT API lets you manage customer satisfaction surveys that are automatically sent after conversation resolution. Surveys collect a rating (default 1-5 stars; configurable to emoji, thumbs, or an NPS 0-10 scale) and an optional text comment.

The admin endpoints (/surveys, the unprefixed list, /analytics, and GET/PUT /config) are authenticated by a dashboard session today — they are not reachable with an API key. The only genuinely API-key-free endpoints are the token-based public survey routes: GET /csat/rate, GET /csat/{token}, and POST /csat/{token}/submit.

How It Works

  1. A conversation is resolved
  2. After a configurable delay (1-72 hours, default driven by survey_delay_hours), a CSAT survey email is sent
  3. The customer clicks a one-click rating link or opens the full survey
  4. Results are aggregated in the analytics dashboard

List Surveys

Admin list of every CSAT survey for the tenant — answered and unanswered — so survey delivery is observable (dashboard session required; not API-key reachable). A survey created on resolve whose email never went out appears here with status: "not_sent". For answered responses only, with filters, use the filtered response list.

cURL
curl "https://apps.aurionai.net/api/v1/csat/surveys?limit=10" \
  -H "X-API-Key: itsm_sk_live_xxxx"

limit defaults to 50 (range 1-200); offset defaults to 0.

Response:

{
  "items": [
    {
      "id": "1f3c9a8e-0b21-4d77-9c54-2f1a6e8b0c3d",
      "conversation_id": "0a2b4c6d-8e10-4321-b9a7-1c3e5f7a9b0d",
      "contact_id": "7e9d1b3f-5a27-4c81-9f60-2d4b6a8c0e12",
      "rating": 5,
      "comment": "Very helpful, resolved my issue quickly!",
      "channel": "email",
      "sent_at": "2026-03-07T14:00:00Z",
      "opened_at": "2026-03-07T16:05:00Z",
      "responded_at": "2026-03-07T16:30:00Z",
      "expires_at": "2026-03-14T14:00:00Z",
      "created_at": "2026-03-07T13:59:00Z",
      "status": "responded"
    }
  ],
  "total": 85,
  "limit": 10,
  "offset": 0
}

Items are ordered newest-created first. status is derived from the timestamps (see Survey Lifecycle); rating, comment and responded_at are null until the survey is answered.

Filtered Response List

GET /api/v1/csat (no /surveys suffix) lists answered surveys only, newest response first, with the same item fields minus expires_at and status. It defaults limit to 50 with a max of 100, and accepts additional filters:

Query paramTypeDescription
sinceISO-8601 datetimeLower bound on responded_at (inclusive)
untilISO-8601 datetimeUpper bound on responded_at (inclusive)
assignee_idUUIDFilter by the rated conversation's assignee user
team_idUUIDFilter by the rated conversation's assignee team

Filters compose with AND. If since is later than until, the endpoint returns 422.

cURL
curl "https://apps.aurionai.net/api/v1/csat?since=2026-03-01T00:00:00Z&until=2026-03-08T23:59:59Z&team_id=7e9d1b3f-5a27-4c81-9f60-2d4b6a8c0e12" \
  -H "X-API-Key: itsm_sk_live_xxxx"

CSAT Analytics

Get aggregated CSAT metrics and trends. This endpoint takes no query parameters — the trend is a fixed trailing 30-day window.

curl "https://apps.aurionai.net/api/v1/csat/analytics" \
  -H "X-API-Key: itsm_sk_live_xxxx"

Response:

{
  "total_responses": 85,
  "avg_score": 4.3,
  "promoters": 66,
  "passives": 12,
  "detractors": 7,
  "distribution": {
    "1": 2,
    "2": 5,
    "3": 12,
    "4": 30,
    "5": 36
  },
  "trend_30d": [
    { "day": "2026-03-07", "count": 9, "avg_score": 4.44 }
  ],
  "per_agent": [
    {
      "assignee_user_id": "8c1e2d3f-4a56-4789-b012-3c4d5e6f7a8b",
      "assignee_name": "Jane Agent",
      "response_count": 24,
      "avg_score": 4.6,
      "promoters": 20,
      "passives": 3,
      "detractors": 1
    }
  ]
}

avg_score is null when there are no responses — an unknown average, not a measured 0. distribution is keyed by integer rating. promoters/passives/detractors are computed from the rating buckets (≥4, =3, ≤2 respectively). trend_30d is an array of {day, count, avg_score} for the trailing 30 days; per_agent breaks the same metrics down per assignee.

One-Click Rating

Each survey email contains one-click rating links. When a customer clicks a rating, their response is recorded immediately:

GET https://apps.aurionai.net/api/v1/csat/rate?token=<survey_token>&rating=5

This is a public endpoint — no authentication required. The survey token ensures only the intended recipient can respond. rating accepts 0-10 (to support NPS scales). On success it returns { "status": "thanks", "rating": "5" }. This route is intentionally excluded from the OpenAPI reference (include_in_schema=False), so it does not appear on the API reference page.

Get Survey Metadata

Fetch survey metadata and customization for rendering the public form. Public, token-based — no authentication required. Opening it marks the survey as opened (opened_at).

GET https://apps.aurionai.net/api/v1/csat/<token>

Response:

{
  "id": "1f3c9a8e-0b21-4d77-9c54-2f1a6e8b0c3d",
  "tenant_id": "0a2b4c6d-8e10-4321-b9a7-1c3e5f7a9b0d",
  "conversation_id": "7e9d1b3f-5a27-4c81-9f60-2d4b6a8c0e12",
  "channel": "email",
  "rating": null,
  "already_responded": false,
  "created_at": "2026-03-07T13:59:00Z",
  "survey_question": null,
  "rating_scale": "1-5",
  "followup_enabled": false,
  "followup_threshold": 3,
  "followup_question": null,
  "survey_question_translations": null,
  "followup_question_translations": null
}

The customization fields (survey_question, rating_scale, followup_*, and the per-locale *_translations maps) are merged from the tenant's CSAT configuration so the form can render without a second round-trip. Returns 404 if the token is unknown.

Submit Full Survey

For the full survey form with an optional comment and follow-up answer. Public, token-based — no authentication required.

curl -X POST "https://apps.aurionai.net/api/v1/csat/<token>/submit" \
  -H "Content-Type: application/json" \
  -d '{
    "rating": 4,
    "comment": "Good service, but took a bit long to respond.",
    "followup_answer": "Faster first reply would help."
  }'

Request body:

FieldTypeDescription
ratinginteger (0-10)Required. Score; the default 1-5 star scale uses 1-5, NPS uses 0-10
commentstring (≤2000)Optional free-text comment
followup_answerstring (≤2000)Optional answer to the low-score follow-up prompt

Response:

{
  "ok": true,
  "survey_id": "1f3c9a8e-0b21-4d77-9c54-2f1a6e8b0c3d",
  "conversation_id": "7e9d1b3f-5a27-4c81-9f60-2d4b6a8c0e12",
  "rating": 4
}

Errors:

StatusBodyMeaning
404{ "detail": "Survey not found" }Token is unknown
410{ "detail": "Survey has expired" }Survey link has expired
409{ "detail": "Survey already submitted" }A response was already recorded for this token

Survey Lifecycle

Surveys carry no stored status column. State is derived from these timestamps:

TimestampSet when
sent_atThe survey email is dispatched (null while the survey is created but not yet delivered)
opened_atThe recipient opens the full survey form (GET /csat/{token})
responded_atThe recipient submits a rating
expires_atSet when delivery is claimed; after it passes the survey can no longer be answered. Older surveys may have none, and then expire survey_expiry_days after sent_at

GET /csat/surveys returns the derived state as status, first match wins: responded (responded_at set), expired (delivered and past its expiry), opened (opened_at set), sent (sent_at set), otherwise not_sent. A survey whose email never went out stays not_sent even after the expiry its delivery claim set has passed.

Expiry and duplicate-submission conditions surface only at submit time as HTTP errors: 410 for an expired survey, 409 for one that already has a response.

Rate Limits

EndpointLimit
List surveys (GET /csat/surveys)30/minute
List responses (GET /csat)30/minute
Analytics (GET /csat/analytics)30/minute
Get survey metadata (GET /csat/{token})30/minute
Submit response (POST /csat/{token}/submit)10/minute

The one-click rating link (GET /csat/rate) is not throttled.

API-key requests are also subject to the plan-based limits described in Error Handling → Rate Limiting, which also covers the 429 bodies and headers.

Configuration

CSAT survey settings are managed via a dashboard session (the API key surface does not cover them) or in the admin dashboard under Configuration > CSAT. The configuration is stored as an extensible JSONB blob (csat_settings); the fields below are the ones the API validates and round-trips.

Get CSAT Configuration

curl "https://apps.aurionai.net/api/v1/csat/config" \
  -H "X-API-Key: itsm_sk_live_xxxx"

Response:

{
  "enabled": true,
  "survey_delay_hours": 2,
  "survey_expiry_days": 7,
  "survey_question": null,
  "rating_scale": "1-5",
  "followup_enabled": false,
  "followup_threshold": 3,
  "followup_question": null,
  "survey_question_translations": null,
  "followup_question_translations": null
}

The response is the stored csat_settings blob; keys that were never set are absent or returned with their defaults.

Update CSAT Configuration

PUT /config accepts a partial update — only the fields you send are changed. Send null for a field to clear an override and fall back to the localized default.

curl -X PUT "https://apps.aurionai.net/api/v1/csat/config" \
  -H "X-API-Key: itsm_sk_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "survey_delay_hours": 4,
    "survey_expiry_days": 14,
    "survey_question": "How did we do?",
    "rating_scale": "nps-10",
    "followup_enabled": true,
    "followup_threshold": 6,
    "followup_question": "What could we have done better?"
  }'

Configurable options:

FieldTypeDescription
enabledbooleanEnable or disable CSAT surveys
survey_delay_hoursinteger (1-72)Hours after resolution before sending the survey
survey_expiry_daysinteger (1-30)Days before the survey link expires
survey_questionstring (≤500)Custom survey question; null falls back to the localized default
rating_scaleenumOne of 1-5, emoji, thumbs, nps-10
followup_enabledbooleanShow a low-score follow-up prompt
followup_thresholdinteger (0-10)Ratings at or below this value trigger the follow-up prompt
followup_questionstring (≤500)Prompt shown to detractors
survey_question_translationsobjectPer-locale override map for the survey question. Keys are locale codes (en, fr, nl, de, es, it, pl, sv, da, fi, pt); values ≤500 chars
followup_question_translationsobjectPer-locale override map for the follow-up prompt; same key/length rules

On this page