Overview
The REST API: base URL, authentication, errors, rate limits, and idempotency.
https://app.sentriment.com/api/v1Note
JSON in, JSON out. Every endpoint is versioned under /v1; breaking changes ship as /v2 with 12 months of overlap. The full spec is available as OpenAPI 3.1. New here? Skim the Quickstart first.
Authentication
Every request identifies itself with an API key, created in Settings → API keys and sent as a header: Authorization: Bearer <key>. The key both authenticates you and scopes the request to your project; there is nothing else to configure. Two key types exist because they live in different places:
| Parameter | In | Description |
|---|---|---|
sk_… | server | Secret keys. Full API access. Keep them server-side; we store only a hash and show the key once at creation. |
pk_… | browser | Widget keys. Safe to embed in your site; they only work from origins you allowlist in Settings, and only for submitting feedback and identify. |
Errors
When something goes wrong, the response tells you exactly what and, wherever possible, how to fix it. Errors use the RFC 7807 standard (application/problem+json): a stable type your code can branch on, a human-readable title, the HTTP status, and an actionable detail. Validation errors name the exact field that failed, so there is no guessing:
{
"type": "https://sentriment.com/problems/origin-not-allowed",
"title": "Origin not allowed for this key",
"status": 403,
"detail": "Add https://app.example.com to the project's allowed origins in Settings."
}| Parameter | In | Description |
|---|---|---|
400 invalid-request | status | Body failed validation; detail lists each field problem. |
401 unauthorized | status | Missing, malformed, or revoked key. |
403 origin-not-allowed | status | Widget key used from a non-allowlisted origin. |
404 not-found | status | Resource doesn't exist in this project. |
413 payload-too-large | status | Body exceeds 64 KB (2 MB for POST /transcripts). |
429 rate-limited | status | Limit exceeded; retry after Retry-After seconds. |
Rate limits
Limits protect your project from runaway scripts and abuse. They are per key, per minute, and generously above normal usage. If you hit one, the response is a 429 that says how long to wait; nothing is lost, just retry after that. Every metered response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (seconds until the window resets) so clients can self-throttle; 429s add Retry-After.
| Parameter | In | Description |
|---|---|---|
POST /feedback | sk | 300 / min |
POST /feedback | pk | 30 / min |
GET /search | sk | 60 / min |
POST /transcripts | sk | 60 / min |
POST /users/identify | sk · pk | 120 / min |
Idempotency
The scenario this solves: your request times out, you don't know whether it landed, and retrying blindly would record the same feedback twice. Send an Idempotency-Key header (≤128 chars, unique per logical submission) on POST /feedback; replays return 200 with the original item instead of creating a duplicate. POST /transcripts needs no header: its required external_id is the key, and a repeat returns the existing call without counting it again.
/api/v1/pingsecret or widget keyPing
Key validation and connectivity check: the first call of every integration. Returns the project the key belongs to and whether you're in test or live mode.
curl https://app.sentriment.com/api/v1/ping \
-H "Authorization: Bearer sk_live_…"