Widget API
The widget API is the same API your embedded widget calls. You can call it directly from your backend to ingest feedback from other sources (in-product surveys, support tools, importers from Canny / Featurebase).
Base URL
https://shippulse.app/api/v1Custom domains do not proxy the API. Always call shippulse.app/api/v1 from your server.
Authentication
Two modes:
- Public widget calls — no key required. Origin-checked against the project's domain allowlist. Read-only on roadmap and changelog; write-only on feedback submission (one submission per session, rate-limited).
- Server-to-server calls — pass
Authorization: Bearer <project-api-key>. Generate keys under Settings → API keys. Keys are project-scoped (one key cannot read another project's data). Keys are write-capable; treat them like secrets.
Endpoints
Feedback
POST /feedback— submit a feature request or bug. Body:{ project_slug, title, body, category, email }. Returns{ id, status: "received" }. Rate-limited.GET /feedback/public/:project_slug— public roadmap entries. No auth. Returns paginated list withid,title,status,vote_count,shipped_at.POST /feedback/:id/vote— record an upvote. Body:{ email }. Idempotent per email.
Roadmap
GET /roadmap/:project_slug— full public roadmap, grouped by status (planned, in-progress, shipped). Cached at the edge sixty seconds.PATCH /roadmap/:id— mark a feature shipped (or move it between statuses). Requires server-to-server auth. Body:{ status, shipped_at? }. Triggers the proof-loop auto-DM ifstatus: "shipped".
Changelog
GET /changelog/:project_slug— published changelog entries, newest first.GET /changelog/:project_slug/rss.xml— RSS feed.POST /changelog— create an entry. Server-to-server auth. Body:{ project_slug, title, body, related_feedback_ids }.
Testimonials
GET /testimonials/:project_slug— public testimonials.GET /testimonials/:project_slug/by-feature/:feedback_id— testimonials linked to a specific feature card.
Rate limits
Public widget calls: 30 requests per minute per IP, 5 submissions per hour per email. Server-to-server calls: 600 requests per minute per API key, burstable to 1200. Limits surfaced via X-RateLimit-Remaining and X-RateLimit-Reset response headers; 429 with a Retry-After header when exceeded.
Errors
JSON shape on every non-2xx:
{ "error": "rate_limited", "message": "Too many submissions from this email; retry after 14m." }Error codes used: unauthorized, forbidden, not_found, rate_limited, bad_request, internal. The HTTP status mirrors the code.
Versioning
The API is versioned in the URL (/api/v1). Breaking changes ship as /api/v2; the previous version is supported for at least twelve months after the new version GAs. Deprecation notices appear in response headers (Deprecation, Sunset) on the old version.
Webhooks
Subscribe under Settings → Webhooks. Events fired:
feedback.created,feedback.votedroadmap.status_changed,roadmap.shippedtestimonial.received,testimonial.publishedchangelog.published
Payloads signed with X-ShipPulse-Signature (HMAC-SHA256). Retry policy: exponential backoff, up to 24h, then surfaced in the dashboard.