Feedback API
Almirant exposes a public REST API (not MCP) for ingesting feedback from widgets embedded in websites or from server-to-server integrations. This API is independent of the MCP server and does not require an Almirant API Key.
Authentication
The Feedback API uses an authentication system based on Public Keys and widget tokens:
- Public Key (
pk_...): Identifies the feedback source. Obtained when creating a feedback source in Almirant and safe to expose on the frontend. - Widget Token: A temporary signed token obtained through the
bootstrapendpoint. It has a limited duration and is used to validate ingestion requests.
Endpoints
GET /feedback/widget/bootstrap
Initializes the feedback widget. Returns the source configuration and a temporary signed token required to submit feedback.
Query Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| publicKey | string | Yes | Feedback source Public Key (pk_...) |
Example request:
curl "https://api.almirant.ai/feedback/widget/bootstrap?publicKey=pk_abc123def456"
Successful response (200):
{
"success": true,
"data": {
"source": {
"publicKey": "pk_abc123def456",
"type": "widget",
"name": "Web App Feedback"
},
"token": "eyJzb3VyY2VJZCI6Ii4uLiJ9.a1b2c3d4e5f6",
"expiresAt": 1708531200,
"config": {
"requireCaptcha": true
}
}
}
Errors:
| Code | Description |
|---|---|
| 404 | Feedback source not found for the provided publicKey |
| 403 | The request origin (domain) is not in the allowed domains list |
POST /feedback/ingest
Submits a feedback item. Requires the token obtained from the bootstrap endpoint.
Headers:
Content-Type: application/json
Body:
| Name | Type | Required | Description |
|---|---|---|---|
| publicKey | string | Yes | Feedback source Public Key |
| token | string | Yes | Widget token obtained from bootstrap |
| message | string | Yes | Feedback content (1-5000 characters) |
| category | string | No | Category: bug, feature_request, improvement, question, praise, other |
| string | No | Sender's email | |
| pageUrl | string | No | URL of the page where the feedback was submitted |
| locale | string | No | User's language/locale |
| captchaToken | string | No | hCaptcha token (required if the source has captcha enabled) |
Example request:
curl -X POST "https://api.almirant.ai/feedback/ingest" \
-H "Content-Type: application/json" \
-d '{
"publicKey": "pk_abc123def456",
"token": "eyJzb3VyY2VJZCI6Ii4uLiJ9.a1b2c3d4e5f6",
"message": "The registration form does not validate emails correctly",
"category": "bug",
"email": "[email protected]",
"pageUrl": "https://myapp.com/register",
"locale": "en"
}'
Successful response (201):
{
"success": true,
"data": {
"id": "fb-uuid-001",
"status": "new",
"createdAt": "2025-02-15T10:30:00.000Z"
}
}
Errors:
| Code | Description |
|---|---|
| 400 | Invalid or missing captcha token (when captcha is required) |
| 401 | Invalid or expired widget token |
| 403 | The request origin (domain) is not allowed |
| 404 | Feedback source not found |
| 409 | Duplicate feedback detected (same content submitted recently) |
| 429 | Rate limit exceeded |
Full integration flow
1. Widget loads on the user's page
|
2. GET /feedback/widget/bootstrap?publicKey=pk_...
|-- Obtains temporary token + configuration
|
3. User writes feedback and submits
|
4. POST /feedback/ingest
|-- publicKey + token + message + metadata
|
5. Feedback appears in Almirant as a new item
Protections
The API includes the following protections:
- Origin validation: Only accepts requests from the domains configured in the feedback source (supports wildcards like
*.mydomain.com) - Signed widget tokens: HMAC-SHA256 tokens with time-based expiration
- Rate limiting: Limits the number of requests per IP and source within a time window
- Deduplication: Detects and rejects duplicate feedback submitted recently (based on SHA-256 hash of normalized content)
- hCaptcha: Optional captcha verification per source (enabled by default)
Feedback categories
| Category | Description |
|---|---|
bug | Bug report or malfunction |
feature_request | New feature request |
improvement | Improvement suggestion for existing functionality |
question | Question or information request |
praise | Positive feedback |
other | Default category when none is specified |
Server-to-server integration
For backend integrations (without a widget), the flow is the same: first call bootstrap to obtain a token, then submit the feedback to ingest. The difference is that you must ensure the origin domain is in the feedback source's allowed list, or configure the source without domain restrictions.
Ingested feedback can be linked to Idea Hub items using the MCP tool link_feedback_to_idea_item. This creates traceability between user feedback and product decisions.