Skip to main content

Produktly API (1.0.0)

Download OpenAPI specification:Download

The Produktly REST API gives you programmatic access to your changelogs, roadmaps, feedback widgets, NPS widgets, tags, and analytics. It exposes the same functionality as the MCP server, over plain HTTP.

Base URL

https://api.produktly.com/api/v1

Authentication

All endpoints (except GET /openapi.json) require an API key passed as a Bearer token.

  1. Sign in to Produktly and open Settings → API keys.
  2. Generate a new key and copy it. The same key works for both REST and MCP.
  3. Send it on every request:
GET /api/v1/changelogs HTTP/1.1
Host: api.produktly.com
Authorization: Bearer <your-api-key>

Missing or invalid keys return 401 unauthorized. Treat the key like a password — anyone with it can read and write your Produktly data.

Response format

List endpoints return an envelope with a data array and pagination metadata:

{
  "data": [ { "id": 1, "name": "..." } ],
  "pagination": { "total": 42, "limit": 50, "offset": 0 }
}

Single-resource endpoints (e.g. GET /roadmaps/{id}) return the resource directly, no envelope.

Pagination

List endpoints accept limit (default 50, max 100) and offset (default 0) query parameters. Date filters (startDate, endDate) compose with pagination where supported.

Errors

Errors come back in a consistent shape:

{
  "error": {
    "code": "invalid_tag_names",
    "message": "Unknown tag names: foo. Use GET /v1/tags to see available tags.",
    "details": { "missing": ["foo"] }
  }
}

Common codes:

  • unauthorized (401) — missing or invalid API key
  • not_found (404) — resource doesn't exist or doesn't belong to your company
  • validation_error (400) — invalid request parameters
  • rate_limit_exceeded (429) — see Rate limits below
  • internal_error (500) — server-side problem; safe to retry

Rate limits

Every API key is limited to 60 requests per minute. Every response includes:

  • X-RateLimit-Limit: total allowed in the window
  • X-RateLimit-Remaining: remaining quota
  • X-RateLimit-Reset: Unix seconds when the bucket refills

When you exceed the limit you'll get 429 rate_limit_exceeded with a Retry-After header. Back off and retry.

Changelogs

List changelogs

Authorizations:
BearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

List posts in a changelog

Authorizations:
BearerAuth
path Parameters
changelogId
required
integer > 0
query Parameters
limit
integer ( 0 .. 100 ]
Default: 50
offset
integer or null >= 0
Default: 0
startDate
string
endDate
string

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Create a changelog post

Authorizations:
BearerAuth
path Parameters
changelogId
required
integer > 0
Request Body schema: application/json
title
required
string non-empty
description
string
date
string
active
boolean
tagNames
Array of strings

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "description": "string",
  • "date": "string",
  • "active": true,
  • "tagNames": [
    ]
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "title": "string",
  • "description": "string",
  • "date": "2019-08-24T14:15:22Z",
  • "active": true,
  • "tags": [
    ]
}

Update a changelog post

Authorizations:
BearerAuth
path Parameters
changelogId
required
integer > 0
postId
required
integer > 0
Request Body schema: application/json
title
string
description
string
date
string
active
boolean
tagNames
Array of strings

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "description": "string",
  • "date": "string",
  • "active": true,
  • "tagNames": [
    ]
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "title": "string",
  • "description": "string",
  • "date": "2019-08-24T14:15:22Z",
  • "active": true,
  • "tags": [
    ]
}

Feedback Widgets

List feedback widgets

Authorizations:
BearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

List feedback responses

Authorizations:
BearerAuth
path Parameters
widgetId
required
integer > 0
query Parameters
limit
integer ( 0 .. 100 ]
Default: 50
offset
integer or null >= 0
Default: 0
startDate
string
endDate
string

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Roadmaps

List roadmaps

Authorizations:
BearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Get roadmap with sections and items

Authorizations:
BearerAuth
path Parameters
roadmapId
required
integer > 0
query Parameters
startDate
string
endDate
string
latestCount
integer ( 0 .. 100 ]
limit
integer ( 0 .. 100 ]
query
string
tagNames
Array of strings

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "publicName": "string",
  • "active": true,
  • "customDomain": "string",
  • "publicId": "string",
  • "sections": [
    ]
}

NPS Widgets

List NPS widgets

Authorizations:
BearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Get NPS score breakdown

Authorizations:
BearerAuth
path Parameters
widgetId
required
integer > 0
query Parameters
startDate
string
endDate
string

Responses

Response samples

Content type
application/json
{
  • "npsScore": 0,
  • "totalResponses": 0,
  • "promoters": {
    },
  • "passives": {
    },
  • "detractors": {
    }
}

List NPS responses

Authorizations:
BearerAuth
path Parameters
widgetId
required
integer > 0
query Parameters
limit
integer ( 0 .. 100 ]
Default: 50
offset
integer or null >= 0
Default: 0
startDate
string
endDate
string

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Stats

Widget stats by entity type

Authorizations:
BearerAuth
path Parameters
entityType
required
string
Enum: "tour" "checklist" "smartTip" "announcement" "changelog" "npsWidget" "roadmap"
query Parameters
startDate
string
endDate
string
entityId
integer > 0

Responses

Response samples

Content type
application/json
{
  • "entityType": "string",
  • "period": {
    },
  • "widgets": [
    ]
}

Company-wide stats summary

Authorizations:
BearerAuth
query Parameters
startDate
string
endDate
string

Responses

Response samples

Content type
application/json
{
  • "period": {
    },
  • "previousPeriod": {
    },
  • "features": [
    ]
}

Tags

List tags

Authorizations:
BearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}