Reporting via the API
Pull responses, engagement stats, and score distributions for automated pipelines.
Prefer MCP for most reporting. If you want ad-hoc summaries, CSAT breakdowns, or to explore responses in conversation, use the MCP server instead — no API keys or scripts required. This guide is for automated pipelines (cron, GitHub Actions, data warehouses) that need programmatic, repeatable access.
The server-to-server API lets your backend pull Confetti data on a schedule or integrate it into custom dashboards.
Prerequisites
- A secret API key (
cfti_sk_…) created on the Setup page. - The survey ID — visible in the survey URL or from
GET /surveys. - For score distributions, the question IDs of your rating questions — from
GET /surveys/{surveyId}.
All requests use:
Authorization: Bearer cfti_sk_<your-secret-key>The base URL is https://confetti.gov.sg/api.
Choose the right endpoint
| What you want | Endpoint | MCP equivalent |
|---|---|---|
| Every answer, row by row | GET …/responses | list_responses |
| Funnel metrics (views → responses) | GET …/stats | Dashboard or API only |
| CSAT / NPS-style score breakdown | GET …/score-distributions | get_score_distributions |
See the Stats overview for timeRange values.
List responses
curl -s "https://confetti.gov.sg/api/v1/protected/surveys/$SURVEY_ID/responses?limit=50" \
-H "Authorization: Bearer $SECRET_KEY"Query parameters:
| Parameter | Description |
|---|---|
cursor | Opaque cursor from the previous page's nextCursor |
limit | Page size, 1–100 (default 50) |
respondent | Filter to a single respondent identifier |
after / before | Inclusive createdAt window (ISO 8601 date-times) |
Each response includes data (answers keyed by question ID), respondent,
clientMetadata, and createdAt.
Engagement stats
Engagement funnel metrics are API-only — use this when you need views, dismissals, and response counts in a pipeline.
curl -s "https://confetti.gov.sg/api/v1/protected/surveys/$SURVEY_ID/stats" \
-H "Authorization: Bearer $SECRET_KEY"Example response:
{
"data": {
"totalViews": 1200,
"uniqueViewers": 980,
"totalDismissals": 340,
"uniqueDismissers": 310,
"totalResponses": 85,
"uniqueResponders": 82
}
}No query parameters — stats cover the survey's full lifetime.
Score distributions
curl -s "https://confetti.gov.sg/api/v1/protected/surveys/$SURVEY_ID/score-distributions?questionIds=$QUESTION_ID&timeRange=last-30-days" \
-H "Authorization: Bearer $SECRET_KEY"timeRange values
| Value | Description |
|---|---|
all-time | Every response since the survey was created |
last-7-days | Rolling 7-day window |
last-30-days | Rolling 30-day window |
q1-2026 … q4-2026 | Calendar quarter (current or previous 4 quarters) |
custom_2026-01-01_2026-01-31 | Custom inclusive date range (custom_<start>_<end>) |
Example: scheduled pipeline
For a weekly digest you run on a schedule:
curl -s "https://confetti.gov.sg/api/v1/protected/surveys/$SURVEY_ID/stats" \
-H "Authorization: Bearer $SECRET_KEY" | jq '.data.totalResponses'
curl -s "https://confetti.gov.sg/api/v1/protected/surveys/$SURVEY_ID/score-distributions?questionIds=$QUESTION_ID&timeRange=last-7-days" \
-H "Authorization: Bearer $SECRET_KEY" | jq '.data.current'For the same report on demand in conversation, use MCP reporting instead.
Real-time delivery
To push each new response to Slack or a helpdesk immediately, use webhooks — not the API.
Was this page helpful?