Home
Management API · REST · JSON

ReleasePad Management API

Create, update, schedule and publish changelog posts, manage categories, and pull view analytics from your own scripts, CI pipelines and internal tools. Everything speaks JSON, every response uses the same envelope, and posts are written in plain Markdown.

Create your first post https://pro.releasepad.io/api/v2/manage

Introduction

The Management API is the programmatic version of the ReleasePad dashboard. Anything you can do to a post or a category from the web editor, you can do from here: draft a release note from your CI pipeline, publish it when the deploy lands, schedule it for the next morning, or sync categories across products. It also exposes the raw view records behind your public changelog page and in-app widget, so you can push them into your own analytics stack.

It is a plain JSON REST API over HTTPS. There is no SDK to install: any HTTP client works. Post bodies are exchanged as Markdown, so the same text you would paste into a GitHub release works as a request body.

Base URL

https://pro.releasepad.io/api/v2/manage

Format

JSON request & response bodies. Send Content-Type: application/json on writes.

Availability

Paid plans only. See pricing.

Authentication

Every request is authenticated with an account API key sent as a Bearer token in the Authorization header. Keys are created by an account admin in the dashboard under My Account → Settings → API Keys, and are shown in full on that page so you can copy them again later.

API key all endpoints
  • A key belongs to the account, not to one product. It can read and write every product in the account.
  • Requests made with a key act as the admin who created it. Posts created through the API are attributed to that user in the dashboard. If that admin is later removed, the key keeps working as another active admin of the account.
  • Keys do not expire. Revoking a key from the API Keys page is the only way to stop it, and takes effect immediately.
  • The dashboard records when each key was last used, so unused keys are easy to spot and revoke.
  • Treat keys like passwords: keep them in a secrets manager or CI secret, never in client-side code. The product's public token used by the widget is a different credential and does not work here.
Authorization header
curl "https://pro.releasepad.io/api/v2/manage/products" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"

A missing, malformed or revoked key answers 401. A valid key on an account that is still on trial answers 403: the Management API is available on paid plans only.

Quickstart

Three calls take you from an empty terminal to a published release note. Find your product, pick a category, then create the post with draft: false.

1 · Find your product id
curl "https://pro.releasepad.io/api/v2/manage/products" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"

# → data.products[0].id is 20, data.products[0].product_uri is "acme-app"
2 · Pick a category
curl "https://pro.releasepad.io/api/v2/manage/products/20/categories" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"

# → data.categories[].id, e.g. 64 for "New Feature"
3 · Publish a post
curl -X POST "https://pro.releasepad.io/api/v2/manage/products/20/posts" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "title": "Dark mode is finally here",
  "category_id": 64,
  "draft": false,
  "body": "## Dark mode\n\nToggle dark mode from any screen using the new switch in **Settings → Appearance**. Your choice syncs across devices.\n\n- Follows your system theme by default\n- Every chart and table has been re-tinted for contrast"
}
EOF

Response format

Every response follows the JSend convention and carries a top-level status, so you can branch on one field before touching the payload.

"success"

Request worked. The payload is under data, keyed by resource name (post, posts, category, …).

"fail"

Validation failed. data maps each field name to a list of messages.

"error"

The request could not be served. A human-readable message explains why.

success
{
  "status": "success",
  "data": {
    "post": { "id": 482, "title": "Dark mode is finally here", ... }
  }
}
fail · 422
{
  "status": "fail",
  "data": {
    "title": ["can't be blank"],
    "body": ["needs to have at least 100 characters."]
  }
}

Timestamps are ISO 8601 in UTC with microsecond precision, for example 2026-09-02T10:00:00.000000Z. Ids are integers.

Errors

Standard HTTP status codes are used alongside the JSend body.

Code Status Meaning
200successThe request worked.
201successA post or category was created. The new resource is in the body.
401errorMissing, malformed or revoked API key. message is "Missing or invalid authorization token".
403errorThe account is on trial. Upgrade to a paid plan to use the Management API.
404errorThe product, post or category does not exist, is deleted, or belongs to another account. Non-numeric ids also answer 404.
413errorThe post body is larger than 512 KB.
422failValidation failed. data lists the offending fields, e.g. {"title": ["can't be blank"]}.
500errorUnexpected server error. Safe to retry.

Pagination

List endpoints are paginated with a ?page=N query parameter, 1-indexed and defaulting to 1. Every paginated response includes a pagination object with the current page, the total number of pages and the total record count, so you know when to stop. Page size is fixed per endpoint:

Endpoint Per page Order
List products10Newest first
List posts45Most recently created first
Post views10Newest first
Changelog views10Newest first
pagination object
{
  "status": "success",
  "data": {
    "posts": [ ... ],
    "pagination": { "page": 2, "pages": 3, "count": 112 }
  }
}

List categories is not paginated and returns every active category of the product.

Product identifiers

Most endpoints are scoped to one product through the {product_id} path segment. It accepts either the product's numeric id or its product_uri, the slug that appears in the public changelog URL (pro.releasepad.io/en/acme-app). Both are returned by List products.

by numeric id
GET /api/v2/manage/products/20/posts
by product_uri
GET /api/v2/manage/products/acme-app/posts

A product that does not exist, has been deleted, or belongs to a different account answers 404 with the message "Invalid Product". Posts and categories are always resolved inside the product in the URL, so a valid post id under the wrong product is also a 404.

Products

The products in your account. Read-only: products are created and configured in the dashboard.

GET /api/v2/manage/products

List products

API key

Returns the active products in your account, newest first. Use it to discover the id or product_uri that the other endpoints take as {product_id}.

public_token is the credential used by the widget and the public read endpoints, so this call is also a convenient way to fetch it programmatically. posts_count counts non-deleted posts, drafts included. logo_url is null when no logo has been uploaded.

Parameters

Name In Description
pagequeryPage number, 1-indexed. Default 1. 10 products per page.
cURL
curl "https://pro.releasepad.io/api/v2/manage/products" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "products": [
      {
        "id": 20,
        "name": "Acme App",
        "website": "https://acme.app",
        "product_uri": "acme-app",
        "public_token": "SFMyNTY.g2gDYQ9uBgBK3Xj2kwFiAAFRgA.p7Zs4mT6yZ1cB9dF3hA5sK8jN0qW2eR7Q3jK5X8vN2",
        "posts_count": 37,
        "logo_url": "https://pro.releasepad.io/uploads/acme-app/logo.png",
        "created_at": "2025-11-04T09:12:31.000000Z",
        "updated_at": "2026-08-30T16:40:02.000000Z"
      }
    ],
    "pagination": { "page": 1, "pages": 1, "count": 1 }
  }
}
GET /api/v2/manage/products/{product_id}

Get a product

API key

Returns one product by numeric id or product_uri. Same shape as the list items.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
cURL
curl "https://pro.releasepad.io/api/v2/manage/products/acme-app" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "product": {
      "id": 20,
      "name": "Acme App",
      "website": "https://acme.app",
      "product_uri": "acme-app",
      "public_token": "SFMyNTY.g2gDYQ9uBgBK3Xj2kwFiAAFRgA.p7Zs4mT6yZ1cB9dF3hA5sK8jN0qW2eR7Q3jK5X8vN2",
      "posts_count": 37,
      "logo_url": "https://pro.releasepad.io/uploads/acme-app/logo.png",
      "created_at": "2025-11-04T09:12:31.000000Z",
      "updated_at": "2026-08-30T16:40:02.000000Z"
    }
  }
}

Posts

Your release notes: drafts, scheduled posts and published posts alike.

The post object

One shape is used everywhere a post is returned, in lists and on its own. Fields marked writable can be sent when creating or updating a post; the rest are computed by ReleasePad.

Field Type Description
idintegerUnique post id.
title stringRequired on create. The headline shown in the widget and on the changelog page.
body stringRequired on create. The content as Markdown. At least 100 characters of readable text, at most 512 KB.
blurbstringPreview text: the first ~220 characters of the body's paragraph text, tags stripped. Regenerated whenever body changes.
category_id integerRequired on create. Id of one of the product's categories. Write-only: responses carry the expanded category instead.
categoryobjectThe post's category as { id, name, background_color }, or null.
draft booleantrue keeps the post out of the widget and changelog page. Defaults to true on create, so a post is never published by accident. Send false to publish.
publish_at datetimeWhen the post becomes visible. Defaults to now on create. Set a future date to schedule: a non-draft post with a future publish_at stays hidden until then. Accepts ISO 8601 with offset (2026-09-10T09:00:00Z) or YYYY-MM-DDTHH:MM, which is read in your account's timezone. Always returned in UTC.
is_private booleanWhen true, the post is hidden from the public changelog and only shown in the widget to the users listed in only_show_to_ids. See identifying widget users.
only_show_to_ids stringComma-separated external user ids (the user_metadata values your widget sends), e.g. "user_9f2c,user_a1b3". Only meaningful with is_private: true; setting is_private to false clears it.
view_counterintegerTotal recorded views of the post.
product_idintegerNumeric id of the owning product.
created_atdatetimeWhen the post was created.
updated_atdatetimeWhen the post was last changed.
post object
{
  "id": 482,
  "title": "Dark mode is finally here",
  "blurb": "Toggle dark mode from any screen using the new switch in Settings → Appearance. Your choice syncs across devices.",
  "body": "## Dark mode\n\nToggle dark mode from any screen using the new switch in **Settings → Appearance**. Your choice syncs across devices.\n\n- Follows your system theme by default\n- Every chart and table has been re-tinted for contrast",
  "draft": false,
  "is_private": false,
  "only_show_to_ids": null,
  "publish_at": "2026-09-02T10:00:00.000000Z",
  "view_counter": 1284,
  "category": { "id": 64, "name": "New Feature", "background_color": "#dcfce7" },
  "product_id": 20,
  "created_at": "2026-09-02T09:55:12.481902Z",
  "updated_at": "2026-09-02T10:00:04.110377Z"
}

Writing the body in Markdown

body is GitHub-flavoured Markdown, sent as a single JSON string with \n line breaks. Plain text works as-is. ReleasePad stores the Markdown you send and renders the HTML for the widget and changelog page on its side, so what you read back is exactly what you wrote.

Supported

  • Headings (# to ######)
  • Paragraphs, bold, italic, inline code, links
  • Ordered and unordered lists
  • Fenced code blocks
  • Images by URL (![alt](https://…))
  • Tables (flattened to one line per row)
  • Inline HTML for bold, italic, links, code, <mark> and <br>

Rules

  • At least 100 characters of readable text (headings, paragraphs, lists and code all count), otherwise 422.
  • At most 512 KB, otherwise 413.
  • Any other HTML (<script>, <div>, <iframe>, …) is stripped, never rendered.
  • Other keys such as content or html in the request are ignored. Only body is read.
  • Posts written in the web editor are stored as the same Markdown, so they read back exactly as written.
body as a JSON string
"body": "## What changed\n\nCSV exports now **stream** instead of buffering, so a 2 GB export starts downloading in under a second.\n\n1. Open any report\n2. Click *Export → CSV*\n\n```bash\ncurl -O https://acme.app/reports/42.csv\n```"
GET /api/v2/manage/products/{product_id}/posts

List posts

API key

Returns the product's posts, most recently created first, drafts and scheduled posts included. Filter by publication status, title or category. Deleted posts are never returned.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
pagequeryPage number, 1-indexed. Default 1. 45 posts per page.
statusqueryall (default), published (not a draft, including scheduled posts), draft, or to_be_published (publish_at in the future).
titlequeryCase-insensitive substring match on the title.
category_idqueryOnly posts in this category.
cURL
curl "https://pro.releasepad.io/api/v2/manage/products/20/posts?status=published&category_id=64" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "posts": [
      {
        "id": 482,
        "title": "Dark mode is finally here",
        "blurb": "Toggle dark mode from any screen using the new switch in Settings → Appearance.",
        "body": "## Dark mode\n\nToggle dark mode from any screen ...",
        "draft": false,
        "is_private": false,
        "only_show_to_ids": null,
        "publish_at": "2026-09-02T10:00:00.000000Z",
        "view_counter": 1284,
        "category": { "id": 64, "name": "New Feature", "background_color": "#dcfce7" },
        "product_id": 20,
        "created_at": "2026-09-02T09:55:12.481902Z",
        "updated_at": "2026-09-02T10:00:04.110377Z"
      }
    ],
    "pagination": { "page": 1, "pages": 1, "count": 12 }
  }
}
GET /api/v2/manage/products/{product_id}/posts/{id}

Get a post

API key

Returns a single post, whatever its status. Answers 404 if the post has been deleted or does not belong to the product in the URL.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
id *pathThe post id.
cURL
curl "https://pro.releasepad.io/api/v2/manage/products/20/posts/482" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "post": {
      "id": 482,
      "title": "Dark mode is finally here",
      "blurb": "Toggle dark mode from any screen using the new switch in Settings → Appearance.",
      "body": "## Dark mode\n\nToggle dark mode from any screen ...",
      "draft": false,
      "is_private": false,
      "only_show_to_ids": null,
      "publish_at": "2026-09-02T10:00:00.000000Z",
      "view_counter": 1284,
      "category": { "id": 64, "name": "New Feature", "background_color": "#dcfce7" },
      "product_id": 20,
      "created_at": "2026-09-02T09:55:12.481902Z",
      "updated_at": "2026-09-02T10:00:04.110377Z"
    }
  }
}
POST /api/v2/manage/products/{product_id}/posts

Create a post

API key

Creates a post in the product. The body is a flat JSON object; title, body and category_id are required. Everything else is optional and falls back to the defaults listed in the post object. Unknown keys are ignored.

A post is created as a draft unless you send "draft": false. To publish immediately, send draft: false and omit publish_at. To schedule, send draft: false with a future publish_at. Responds 201 with the created post.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
title *bodyPost headline.
body *bodyMarkdown content, 100+ readable characters, up to 512 KB.
category_id *bodyId of a category of this product.
draftbodyDefault true. Send false to publish.
publish_atbodyDefault now. ISO 8601 with offset, or YYYY-MM-DDTHH:MM in the account timezone.
is_privatebodyDefault false.
only_show_to_idsbodyComma-separated external user ids. Used with is_private: true.
cURL
curl -X POST "https://pro.releasepad.io/api/v2/manage/products/20/posts" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Scheduled maintenance on Sept 10",
    "category_id": 66,
    "draft": false,
    "publish_at": "2026-09-08T09:00",
    "body": "We will be upgrading our primary database on **September 10 from 02:00 to 02:30 UTC**.\n\nDuring that window the API will answer `503` and the dashboard will be read-only. No data will be lost and no action is needed on your side."
  }'
Response · 201
{
  "status": "success",
  "data": {
    "post": {
      "id": 483,
      "title": "Scheduled maintenance on Sept 10",
      "blurb": "We will be upgrading our primary database on September 10 from 02:00 to 02:30 UTC. During that window the API will answer 503 and the dashboard will be read-only.",
      "body": "We will be upgrading our primary database on **September 10 from 02:00 to 02:30 UTC**.\n\nDuring that window ...",
      "draft": false,
      "is_private": false,
      "only_show_to_ids": null,
      "publish_at": "2026-09-08T14:00:00.000000Z",
      "view_counter": 0,
      "category": { "id": 66, "name": "Announcement", "background_color": "#fffbeb" },
      "product_id": 20,
      "created_at": "2026-09-03T15:21:44.902113Z",
      "updated_at": "2026-09-03T15:21:44.902113Z"
    }
  }
}
PATCH /api/v2/manage/products/{product_id}/posts/{id}

Update a post

API key

Updates a post. PATCH and PUT behave the same: the body is a partial object and any key you do not send keeps its current value. Sending a new body replaces the stored Markdown and regenerates the blurb.

This is also how you publish a draft ({"draft": false}), reschedule a post, or take one down without deleting it ({"draft": true}). Setting is_private to false clears only_show_to_ids. Responds with the full updated post.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
id *pathThe post id.
title, body, category_id, draft, publish_at, is_private, only_show_to_idsbodyAll optional. Same rules as Create a post.
cURL
curl -X PATCH "https://pro.releasepad.io/api/v2/manage/products/20/posts/483" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"draft": false, "publish_at": "2026-09-09T09:00:00Z"}'
Response · 200
{
  "status": "success",
  "data": {
    "post": {
      "id": 483,
      "title": "Scheduled maintenance on Sept 10",
      "blurb": "We will be upgrading our primary database on September 10 from 02:00 to 02:30 UTC. ...",
      "body": "We will be upgrading our primary database on **September 10 from 02:00 to 02:30 UTC**. ...",
      "draft": false,
      "is_private": false,
      "only_show_to_ids": null,
      "publish_at": "2026-09-09T09:00:00.000000Z",
      "view_counter": 0,
      "category": { "id": 66, "name": "Announcement", "background_color": "#fffbeb" },
      "product_id": 20,
      "created_at": "2026-09-03T15:21:44.902113Z",
      "updated_at": "2026-09-03T15:30:02.337815Z"
    }
  }
}
DELETE /api/v2/manage/products/{product_id}/posts/{id}

Delete a post

API key

Deletes a post. This is a soft delete: the post disappears from the dashboard, the widget, the changelog page and every API response, and its view records are kept for reporting. The product's posts_count is updated. Answers 404 if the post is already deleted or belongs to another product.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
id *pathThe post id.
cURL
curl -X DELETE "https://pro.releasepad.io/api/v2/manage/products/20/posts/483" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": { "id": 483, "deleted": true }
}

Categories

The labels a post is filed under ("New Feature", "Fix", "Improvement", …). Every post needs one, and the widget and changelog page let readers filter by them.

GET /api/v2/manage/products/{product_id}/categories

List categories

API key

Returns every active category of the product, sorted by name. Not paginated. background_color is the hex colour of the label badge.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
cURL
curl "https://pro.releasepad.io/api/v2/manage/products/20/categories" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "categories": [
      {
        "id": 66,
        "name": "Announcement",
        "background_color": "#fffbeb",
        "product_id": 20,
        "created_at": "2025-11-04T09:12:31.000000Z",
        "updated_at": "2025-11-04T09:12:31.000000Z"
      },
      {
        "id": 65,
        "name": "Fix",
        "background_color": "#fdf4ff",
        "product_id": 20,
        "created_at": "2025-11-04T09:12:31.000000Z",
        "updated_at": "2025-11-04T09:12:31.000000Z"
      },
      {
        "id": 64,
        "name": "New Feature",
        "background_color": "#dcfce7",
        "product_id": 20,
        "created_at": "2025-11-04T09:12:31.000000Z",
        "updated_at": "2025-11-04T09:12:31.000000Z"
      }
    ]
  }
}
GET /api/v2/manage/products/{product_id}/categories/{id}

Get a category

API key

Returns one category. Answers 404 if it has been deleted or belongs to another product.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
id *pathThe category id.
cURL
curl "https://pro.releasepad.io/api/v2/manage/products/20/categories/64" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "category": {
      "id": 64,
      "name": "New Feature",
      "background_color": "#dcfce7",
      "product_id": 20,
      "created_at": "2025-11-04T09:12:31.000000Z",
      "updated_at": "2025-11-04T09:12:31.000000Z"
    }
  }
}
POST /api/v2/manage/products/{product_id}/categories

Create a category

API key

Creates a category in the product. Both name and background_color are required; a missing one answers 422. Responds 201 with the new category.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
name *bodyLabel shown on posts, e.g. "Security".
background_color *bodyBadge colour as a hex string, e.g. "#f5f3ff".
cURL
curl -X POST "https://pro.releasepad.io/api/v2/manage/products/20/categories" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Security", "background_color": "#f5f3ff"}'
Response · 201
{
  "status": "success",
  "data": {
    "category": {
      "id": 71,
      "name": "Security",
      "background_color": "#f5f3ff",
      "product_id": 20,
      "created_at": "2026-09-03T15:40:19.014552Z",
      "updated_at": "2026-09-03T15:40:19.014552Z"
    }
  }
}
PATCH /api/v2/manage/products/{product_id}/categories/{id}

Update a category

API key

Updates a category. PATCH and PUT behave the same: send only the keys you want to change, the rest keep their current value. Posts already filed under the category pick up the new name and colour immediately.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
id *pathThe category id.
namebodyNew label.
background_colorbodyNew hex colour.
cURL
curl -X PATCH "https://pro.releasepad.io/api/v2/manage/products/20/categories/71" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"background_color": "#fee2e2"}'
Response · 200
{
  "status": "success",
  "data": {
    "category": {
      "id": 71,
      "name": "Security",
      "background_color": "#fee2e2",
      "product_id": 20,
      "created_at": "2026-09-03T15:40:19.014552Z",
      "updated_at": "2026-09-03T15:42:51.778201Z"
    }
  }
}
DELETE /api/v2/manage/products/{product_id}/categories/{id}

Delete a category

API key

Deletes a category. This is a soft delete: it no longer appears in List categories or in the dashboard, but posts already filed under it keep their category and keep rendering its label. Answers 404 if the category is already deleted or belongs to another product.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
id *pathThe category id.
cURL
curl -X DELETE "https://pro.releasepad.io/api/v2/manage/products/20/categories/71" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": { "id": 71, "deleted": true }
}

Analytics

The raw view records behind the dashboard charts, one row per view. Country and city are resolved from the IP shortly after the view is recorded, so they can be null on the newest rows. user_metadata is the external user id your widget sent with the view, when you identify widget users.

GET /api/v2/manage/products/{product_id}/posts/{id}/views

List post views

API key

Returns the individual views of one post, newest first. The post's view_counter is the total of these rows. Answers 404 if the post is deleted or not in the product.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
id *pathThe post id.
pagequeryPage number, 1-indexed. Default 1. 10 views per page.
cURL
curl "https://pro.releasepad.io/api/v2/manage/products/20/posts/482/views?page=1" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "views": [
      {
        "id": 90211,
        "ip": "203.0.113.42",
        "user_metadata": "user_9f2c",
        "country": "Germany",
        "city": "Berlin",
        "created_at": "2026-09-03T08:14:57.201334Z"
      },
      {
        "id": 90207,
        "ip": "198.51.100.7",
        "user_metadata": null,
        "country": null,
        "city": null,
        "created_at": "2026-09-03T08:12:03.554910Z"
      }
    ],
    "pagination": { "page": 1, "pages": 129, "count": 1284 }
  }
}
GET /api/v2/manage/products/{product_id}/changelog/views

List changelog page views

API key

Returns the individual page views of the product's public changelog page, newest first. Same row shape as post views. An empty product answers an empty list with count: 0.

Parameters

Name In Description
product_id *pathNumeric product id or product_uri.
pagequeryPage number, 1-indexed. Default 1. 10 views per page.
cURL
curl "https://pro.releasepad.io/api/v2/manage/products/20/changelog/views" \
  -H "Authorization: Bearer $RELEASEPAD_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "views": [
      {
        "id": 44810,
        "ip": "203.0.113.42",
        "user_metadata": null,
        "country": "Germany",
        "city": "Berlin",
        "created_at": "2026-09-03T08:14:31.887120Z"
      }
    ],
    "pagination": { "page": 1, "pages": 61, "count": 604 }
  }
}

Built and maintained by the ReleasePad team · Last updated

Building something with the API?

Tell us what you're building. We're happy to help, and we take endpoint requests seriously.

Contact the team
Try me now!