Developers
Built API-first. Open on every plan.
Everything in the dashboard is available through a REST API, signed webhooks and a native MCP server. You get the same endpoints on Free and Pro, with no enterprise tier and no sales call.
{
"mcpServers": {
"dawnly": {
"url": "https://api.dawnly.io/mcp",
"headers": {
"Authorization": "Bearer dk_live_••••"
}
}
}
}- › search_feedback
- › list_feedback
- › update_feedback_status
- › get_nps_trend
- › get_nps_summary
- › create_changelog_entry
- › get_feedback
- › list_changelog
Connected · scoped to workspace “acme”
From zero to first call in about 90 seconds.
- 01
Create an API key
Go to Settings → API. Keys are scoped to one workspace and you can revoke them at any time.
dk_live_7Hq2•••••••• - 02
Make a request
Every object has a stable public ID from day one. Lists use cursor pagination.
GET /v1/workspaces/acme/posts?sort=votes - 03
Subscribe to events
Register an endpoint, pick the events you want, and check deliveries in the webhook log.
POST /v1/workspaces/acme/webhooks
REST API
Every object. Every plan.
| Method | Path | What it does |
|---|---|---|
| GET | /v1/workspaces/:slug/posts | List posts by status, tag or votes |
| POST | /v1/workspaces/:slug/posts | Submit feedback |
| PATCH | /v1/workspaces/:slug/posts/:id/status | Change a post’s status |
| POST | /v1/workspaces/:slug/posts/:id/votes | Upvote on behalf of a user |
| POST | /v1/workspaces/:slug/posts/:id/merge | Merge a duplicate into a post |
| GET | /v1/workspaces/:slug/posts/:id/comments | Threaded comments |
| GET | /v1/workspaces/:slug/nps/trend | Score trend over time |
| POST | /v1/workspaces/:slug/changelog | Create a changelog entry |
| DELETE | /v1/workspaces/:slug/webhooks/:id | Remove a webhook endpoint |
Webhooks
Signed, logged and retried.
Every delivery carries an HMAC-SHA256 signature. Check it with one line, and use the delivery log in the dashboard to debug any failed attempt.
- feedback.created
- A new post is submitted
- feedback.status_changed
- A post changes status
- nps.response_received
- Someone answers a survey
- changelog.published
- An entry goes live
import { verifyWebhook } from '@dawnly/node'
app.post('/webhooks/dawnly', async (req, res) => {
const event = verifyWebhook(
req.rawBody,
req.headers['x-dawnly-signature'],
process.env.DAWNLY_WEBHOOK_SECRET,
) // throws if the signature is wrong
if (event.type === 'feedback.status_changed') {
await slack.post(`${event.data.title} → ${event.data.status}`)
}
res.sendStatus(200)
})MCP server
Give your AI the whole picture.
The MCP server is a thin, typed layer over the REST API. Each tool calls the same endpoint you would, with the same permissions, rate limits and audit trail.
It works with Claude, Cursor and any other MCP client. Add one URL and your API key.
search_feedbackFind posts about a theme, like “exports”.list_feedbackList posts with filters for status, tag and sort.update_feedback_statusMove a post along the roadmap.get_nps_trendScore over time, by week or month.get_nps_summaryCurrent score and breakdown.create_changelog_entryDraft an entry and link its posts.get_feedbackOne post with its votes and comments.list_changelogPublished and draft entries.
API design principles
cm1x9f2k40001Stable public IDs
Every object has a cuid from the moment it’s created. IDs never change and are never reused.
?cursor=…Cursor pagination
Results stay consistent as you page, even while new posts arrive.
{ error: { code } }One error shape
Every error returns a machine-readable code and a message a person can read.
429 · Retry-AfterFair rate limits
Limits are per key: 60 req/min on Free and 600 on Pro, with standard headers.