Skip to content
Browse docs
Docs / Foundation

API

Send feedback in programmatically from support tools, CRMs, in-app forms or anything internal.

01Which key works where

There are two working paths, and they authenticate differently.

Survey submissions — POST https://api.annsa.ai/surface/submit. Take the key from Settings → Integrations → Survey and send it in the JSON body as api_key, not as a header.

{
  "api_key": "YOUR_SURVEY_KEY",
  "text": "The export keeps timing out on large boards",
  "email": "sam@acme.com"
}

Everything else — use MCP. The remote server at https://app.annsa.ai/mcp authenticates over OAuth in the browser and exposes priorities, specs, actions and search to any MCP client or agent. See Cursor & Claude Code.

There is no general-purpose REST API key today. The in-app endpoints authenticate with your session, so they are not usable from a script or an agent.

02Send one item

POST https://api.annsa.ai/feedback
{
  "text": "The export is too slow on large datasets",
  "customer_name": "Jane Smith",
  "customer_email": "jane@example.com",
  "revenue_band": 199,
  "source": "api"
}

03Send a batch

Same endpoint, an items array instead. Up to 1,000 items per request, and the response carries a result for each one.

{
  "items": [
    {
      "text": "Can't find the export button",
      "customer_email": "alex@example.com",
      "revenue_band": 49
    },
    {
      "text": "Love the new dashboard layout",
      "customer_name": "Sam Lee"
    }
  ]
}

04The fields

What /surface/submit accepts:

FieldTypeRequiredDescription
api_keystringYesYour survey key, in the body
textstringNoThe feedback content
emailstringNoEnables close-the-loop notifications
feedback_typestringNoOne of bug, feature, question, other
page_urlstringNoWhere the feedback was given
user_metadataobjectNoYour own context — user id, plan, anything you want carried through

Richer customer fields — name, revenue, SKU, your own external id — are set on import (CSV, Google Sheets) or over MCP. See Importing feedback.

05Duplicates are skipped

Annsa hashes the text, so the same content submitted twice creates one item. Pass external_id and the second submission is skipped on that id regardless of what the text says.

06What comes back

A new item returns its id:

{ "id": "8ffee9c7-63e6-4e5d-9fb3-387a97bbdc0c" }

A duplicate says so, and names where the original came from:

{
  "id": "8ffee9c7-63e6-4e5d-9fb3-387a97bbdc0c",
  "duplicate": true,
  "original_source": "slack"
}

A batch returns counts and a result per item — total_items, successful, queued, duplicates, failed, plus results, duplicates_list and errors.

07Rate limits

5,000 requests per hour on survey submissions, and 1,000 items per batch request. Your plan's monthly feedback limit applies separately — past it, items are safely held rather than dropped. See Held feedback & plan limits.

08Where it lands

Feedback submitted this way is tagged widget, so you can filter it in the activity log and tell it apart from Slack, CSV and MCP submissions. The source is set for you — you don't pass it.

09The machine-readable spec

Every endpoint here is described in an OpenAPI 3.1 document at annsa.ai/openapi.json — including which credential each one accepts, so an agent can work that out without reading this page. It is served with an open CORS header, so a tool can fetch it directly.

It is also linked from every response on the site as Link: </openapi.json>; rel="service-desc".

10Transcripts

POST https://api.annsa.ai/transcripts/upload
FieldRequiredNotes
textYesThe transcript content. 50 characters minimum, 500,000 maximum
titleYes1–500 characters. Omitting it returns a 422
transcript_typeNoDefaults to discovery
transcript_date · company_name · customer_name · customer_email · revenue_band · skuNoCustomer context — customer_email is what enables close-the-loop notifications

Uploading the same transcript twice is safe; it is recognized rather than duplicated.

Next guideImporting Feedback