> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://api-docs.papertracc.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://api-docs.papertracc.com/_mcp/server.

# Overview

A workspace can run several blogs, each published to the channels it should appear on. The Storefront API returns the blogs published to your channel and their live articles.

## What the API does and doesn't do

The merchant writes, publishes and moderates everything in the Papertracc app, under **Marketing → Blog**. The Storefront API is for the shopper's side. It can:

* read blogs, articles, tags and approved comments
* submit a comment
* count an article view

The API has no endpoints for creating, editing or deleting blogs or articles, and none for moderating comments. Neither the Storefront API nor the Core API does this.

## Blogs

List Blogs returns the blogs published to your channel, ordered by title. A new blog is published to every Online Store and Store API channel unless the merchant chooses otherwise. `articles_count` counts live articles only.

A blog that isn't published to your channel returns `404`, and so do its articles.

## Live articles

An article is live when it is published and its publish date has passed. Scheduled articles appear on their own when the date arrives. Drafts are never returned.

Article handles are unique across the workspace, so an article can be fetched without naming its blog.

Get Article returns `404` once an article stops being live. That happens when the merchant:

* saves a live article as a draft or unpublishes it. Republishing keeps the original publish date unless the merchant reschedules it.
* deletes the article.
* changes the article's handle. The old handle doesn't redirect.
* takes the article's blog off your channel.

Treat `404` as "no longer available" and drop the page or link.

## Listing and search

List Articles returns the newest first. Use `sort_by` to order by oldest first, title, or `most-viewed`. Filters combine, so `blog=journal&tag=care` returns articles that match both.

| Filter     | Matches                                                                                                                            |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `blog`     | Articles in the blog with that handle.                                                                                             |
| `author`   | Articles by the author with that handle.                                                                                           |
| `tag`      | Articles carrying that exact tag. Tags are case-sensitive and keep the merchant's spelling, so take values from List Article Tags. |
| `featured` | `true` for articles the merchant marked as featured, `false` for the rest.                                                         |
| `q`        | Search text, described below.                                                                                                      |

`q` searches titles, excerpts, tags and article bodies using English word forms, so `caring` also finds `care`. It accepts quoted phrases (`"silk scarf"`), `or`, and `-` to leave a word out. A title containing the text also matches. Results are ranked by relevance, with title matches first. If you also send `sort_by`, that order is used instead.

List Article Tags returns up to 100 tags, the most used first, each with the number of live articles carrying it. An article can have up to 20 tags.

List Related Articles returns other live articles from the same blog or sharing at least one tag, newest first.

## Article content

| Field             | Notes                                                                                                                                       |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `body`            | HTML from the merchant's editor.                                                                                                            |
| `excerpt`         | A short summary, or `null`.                                                                                                                 |
| `image`           | The cover image with its alt text, or `null`.                                                                                               |
| `author`          | `null` when the article has no author or the author has been switched off or deleted.                                                       |
| `reading_minutes` | Words in the body divided by 200, rounded up, at least 1.                                                                                   |
| `view_count`      | Views counted with Count Article View.                                                                                                      |
| `seo`             | `title` and `description` are `null` unless the merchant set them; use the article's title and excerpt instead. `image` is the cover image. |

## Comments

Each blog decides how comments work, reported on the article as `comments`:

| `enabled` | `moderated` | What happens to a new comment                             |
| --------- | ----------- | --------------------------------------------------------- |
| `false`   | —           | Comments are closed. Submitting one fails with `422`.     |
| `true`    | `true`      | It waits for the merchant's approval before it is listed. |
| `true`    | `false`     | It is listed straight away.                               |

Create Comment returns the new comment's status, `PENDING` or `APPROVED`, so you can tell the shopper whether it is waiting for approval. A comment caught by the merchant's blocklist also returns `PENDING`, so the sender can't tell it was blocked.

List Comments returns approved comments only, oldest first. Each comment carries the commenter's name, the text and the date. If the merchant has replied, the reply is in `reply` and the time it was saved in `replied_at`; both are `null` otherwise. Show the reply under the comment. The commenter's email address is never returned.

Comment rules:

* The name can be up to 100 characters and the comment up to 2,000. Longer ones fail with `400`.
* Comments are plain text, and markup is removed. An invalid email address, or a comment left empty once markup is removed, fails with `422`.
* Each comment is stored with the shopper's IP address so the merchant can block it. Send `Client-Ip` when you call with a secret key, or every comment carries your server's address.

When the merchant changes a blog's setting:

* Turning comments off hides the comments already there: List Comments returns an empty list and the article's `comments.count` is `0`. Nothing is deleted, so turning comments back on shows them again.
* Switching from moderated to open doesn't approve comments that are already waiting.

### Rate limits

| Limit                      | Applies to                              |
| -------------------------- | --------------------------------------- |
| 5 comments in 15 minutes   | Each shopper, identified by IP address. |
| 200 comments in 15 minutes | Your whole channel.                     |

Over either limit, Create Comment returns `429` with the wait in the message. If your server calls the API with a secret key on behalf of shoppers, send each shopper's IP address in `Client-Ip`. Without it, every shopper shares your server's limit.

## Moderating comments

The merchant moderates comments in the Papertracc app, under **Marketing → Blog → Comments**. In the app the merchant can:

| Action                          | What the shopper sees                                                                                                         |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Approve                         | The comment is listed.                                                                                                        |
| Move to pending                 | The comment is hidden and can be approved again later.                                                                        |
| Mark as spam                    | The comment is hidden and can be approved again later.                                                                        |
| Delete                          | The comment is removed for good.                                                                                              |
| Reply, edit or remove the reply | The change shows in `reply` on the next request. A reply on a comment that isn't approved shows once the comment is approved. |

An approved comment can be taken down at any time by moving it to pending, marking it as spam or deleting it. The change shows on the next request to List Comments, and the article's `comments.count` follows it.

Nobody can edit what a commenter wrote, neither the merchant nor the commenter.

### Blocklist

The merchant can block words and phrases, email addresses or whole email domains, and IP addresses or ranges. A new comment that matches goes straight to spam and is never listed. Comments already posted are not affected.

| Entry                                         | Matches                                                                                     |
| --------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Word or phrase                                | The whole word or phrase in the commenter's name or comment, ignoring case and punctuation. |
| Email address                                 | That address only.                                                                          |
| Email domain, such as `example.com`           | Every address on that domain and its subdomains.                                            |
| IP address or range, such as `203.0.113.0/24` | Comments sent from that address or range.                                                   |

There is no other spam filter.

### Alerts

When a comment is waiting for approval, members who can manage the blog get a notification in the app and by email. Each member can turn either one off under **Blog comments** in their notification settings. Alerts go out at most once every 15 minutes per workspace and give the number of comments waiting.

## View counts

Call Count Article View when a shopper opens an article. Repeat calls from the same shopper for the same article within 6 hours are counted once. Shoppers are told apart by IP address, so a server using a secret key should send `Client-Ip` here too. The count appears as `view_count` and drives `sort_by=most-viewed`.