Public REST API

Feedback Pilgrim Public API

Integrate feedback collection and management into your own applications. Every request is authenticated with a personal API token and automatically scoped to your client — you only ever read and write data that belongs to you.

Base URL

http://feedbackpilgrim.com/api/public/v1
Download OpenAPI 3.1

Authentication

Send a Bearer token with every request. Generate and revoke tokens in your Settings → API. Requests without a valid token return 401.

Request headers
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
Content-Type: application/json

Conventions

  • List endpoints are paginated with per_page and page, returning Laravel data / links / meta envelopes.
  • Validation failures return 422 with a message and field-level errors.
  • Resources outside your client scope return 404; unsupported deletes return 405.

Init

Contact tracking and authentication bootstrap.

POST /init

Bootstrap contact tracking

Initialize contact tracking and (optionally) generate an authentication URL. Typically called when a contact first interacts with your feedback widget. If a `contact` object with an `email` is provided, the contact is created or updated and an `auth_url` is returned. With no contact, an empty object is returned.

Body parameters

contact
object

Contact attributes. Requires `email` to create/update a contact. Unknown keys are stored as metadata.

releaseNotes
object

Optional release-notes widget configuration.

testimonials
object

Optional testimonials widget configuration.

Responses

200 OK. Returns an auth URL when a contact was supplied, otherwise an empty object.
401 Missing or invalid API token.

Request

curl -X POST "http://feedbackpilgrim.com/api/public/v1/init" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "contact": {
        "name": "John Doe",
        "email": "[email protected]",
        "mrr": 99.99,
        "ltv": 1200,
        "avatar": "https://example.com/avatar.jpg",
        "plan": "premium"
    },
    "releaseNotes": {
        "show": true
    }
}'

Response

200 application/json
{
    "auth_url": "https://acme.feedbackpilgrim.com/authenticate-contact?contactUuid=550e8400-e29b-41d4-a716-446655440000"
}

Posts

Feedback posts from contacts.

GET /posts

List posts

Parameters

search
query
string

Partial-match search.

status
query
string
pending in_progress completed

Filter by post status.

board_id
query
integer

Filter posts by board ID.

tag
query
string

Filter by exact tag title.

published
query
boolean

When `true`, only published posts; when `false`, only drafts.

sort_by
query
string default 'created_at'
created_at updated_at title status published_at
sort_direction
query
string default 'desc'
asc desc
per_page
query
integer default 15

Items per page.

page
query
integer default 1

Page number.

Responses

200 Paginated list of posts.
401 Missing or invalid API token.

Request

curl "http://feedbackpilgrim.com/api/public/v1/posts" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

200 application/json
{
    "data": [
        {
            "id": 1,
            "client_id": 1,
            "stage_id": 1,
            "board_id": 1,
            "contact_id": 1,
            "title": "string",
            "content": "string",
            "notes": "string",
            "status": "pending",
            "stage_position": 1,
            "published_at": "2026-06-15T10:00:00Z",
            "archived_at": "2026-06-15T10:00:00Z",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "contact": {
                "id": 1,
                "uuid": "string",
                "user_id": 1,
                "client_id": 1,
                "name": "string",
                "email": "[email protected]",
                "notes": "string",
                "avatar": "string",
                "mrr": 1,
                "ltv": 1,
                "created_at": "2026-06-15T10:00:00Z",
                "updated_at": "2026-06-15T10:00:00Z",
                "tags": [],
                "votes": []
            },
            "tags": [],
            "votes": [],
            "comments": []
        }
    ],
    "links": {
        "first": "string",
        "last": "string",
        "prev": "string",
        "next": "string"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "string",
        "per_page": 1,
        "to": 1,
        "total": 1
    }
}
POST /posts

Create a post

Body parameters required

title required
string
content required
string
status
string
pending in_progress completed
board_id
integer

Board ID belonging to your client. Defaults to the client's first board.

tags
integer[]

Tag IDs belonging to your client.

Responses

201 Post created.
401 Missing or invalid API token.
422 The request failed validation.

Request

curl -X POST "http://feedbackpilgrim.com/api/public/v1/posts" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "title": "Add dark mode",
    "content": "Please support a dark theme.",
    "status": "pending",
    "tags": [
        1,
        2
    ],
    "board_id": 1
}'

Response

201 application/json
{
    "id": 1,
    "client_id": 1,
    "stage_id": 1,
    "board_id": 1,
    "contact_id": 1,
    "title": "string",
    "content": "string",
    "notes": "string",
    "status": "pending",
    "stage_position": 1,
    "published_at": "2026-06-15T10:00:00Z",
    "archived_at": "2026-06-15T10:00:00Z",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "contact": {
        "id": 1,
        "uuid": "string",
        "user_id": 1,
        "client_id": 1,
        "name": "string",
        "email": "[email protected]",
        "notes": "string",
        "avatar": "string",
        "mrr": 1,
        "ltv": 1,
        "created_at": "2026-06-15T10:00:00Z",
        "updated_at": "2026-06-15T10:00:00Z",
        "tags": [
            {
                "id": 1,
                "client_id": 1,
                "title": "string",
                "created_at": "2026-06-15T10:00:00Z",
                "updated_at": "2026-06-15T10:00:00Z",
                "posts_count": 1,
                "contacts_count": 1
            }
        ],
        "votes": [
            {
                "id": 1,
                "contact_id": 1
            }
        ]
    },
    "tags": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ],
    "comments": [
        {
            "id": 1,
            "content": "string"
        }
    ]
}
GET /posts/{post}

Get a post

Parameters

post
path · required
integer

Post ID.

Responses

200 The post, including votes and comments.
401 Missing or invalid API token.
404 Resource not found within your client scope.

Request

curl "http://feedbackpilgrim.com/api/public/v1/posts/{post}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

200 application/json
{
    "id": 1,
    "client_id": 1,
    "stage_id": 1,
    "board_id": 1,
    "contact_id": 1,
    "title": "string",
    "content": "string",
    "notes": "string",
    "status": "pending",
    "stage_position": 1,
    "published_at": "2026-06-15T10:00:00Z",
    "archived_at": "2026-06-15T10:00:00Z",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "contact": {
        "id": 1,
        "uuid": "string",
        "user_id": 1,
        "client_id": 1,
        "name": "string",
        "email": "[email protected]",
        "notes": "string",
        "avatar": "string",
        "mrr": 1,
        "ltv": 1,
        "created_at": "2026-06-15T10:00:00Z",
        "updated_at": "2026-06-15T10:00:00Z",
        "tags": [
            {
                "id": 1,
                "client_id": 1,
                "title": "string",
                "created_at": "2026-06-15T10:00:00Z",
                "updated_at": "2026-06-15T10:00:00Z",
                "posts_count": 1,
                "contacts_count": 1
            }
        ],
        "votes": [
            {
                "id": 1,
                "contact_id": 1
            }
        ]
    },
    "tags": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ],
    "comments": [
        {
            "id": 1,
            "content": "string"
        }
    ]
}
PATCH /posts/{post}

Update a post

Parameters

post
path · required
integer

Post ID.

Body parameters required

title
string
content
string
status
string
pending in_progress completed
board_id
integer

Board ID belonging to your client. Defaults to the client's first board.

tags
integer[]

Tag IDs belonging to your client.

Responses

200 Updated post.
401 Missing or invalid API token.
404 Resource not found within your client scope.
422 The request failed validation.

Request

curl -X PATCH "http://feedbackpilgrim.com/api/public/v1/posts/{post}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "status": "in_progress"
}'

Response

200 application/json
{
    "id": 1,
    "client_id": 1,
    "stage_id": 1,
    "board_id": 1,
    "contact_id": 1,
    "title": "string",
    "content": "string",
    "notes": "string",
    "status": "pending",
    "stage_position": 1,
    "published_at": "2026-06-15T10:00:00Z",
    "archived_at": "2026-06-15T10:00:00Z",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "contact": {
        "id": 1,
        "uuid": "string",
        "user_id": 1,
        "client_id": 1,
        "name": "string",
        "email": "[email protected]",
        "notes": "string",
        "avatar": "string",
        "mrr": 1,
        "ltv": 1,
        "created_at": "2026-06-15T10:00:00Z",
        "updated_at": "2026-06-15T10:00:00Z",
        "tags": [
            {
                "id": 1,
                "client_id": 1,
                "title": "string",
                "created_at": "2026-06-15T10:00:00Z",
                "updated_at": "2026-06-15T10:00:00Z",
                "posts_count": 1,
                "contacts_count": 1
            }
        ],
        "votes": [
            {
                "id": 1,
                "contact_id": 1
            }
        ]
    },
    "tags": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ],
    "comments": [
        {
            "id": 1,
            "content": "string"
        }
    ]
}
DELETE /posts/{post}

Delete a post (not supported)

Deleting posts via the public API is not supported and always returns `405 Method Not Allowed`.

Parameters

post
path · required
integer

Post ID.

Responses

401 Missing or invalid API token.
405 Operation not supported.

Request

curl -X DELETE "http://feedbackpilgrim.com/api/public/v1/posts/{post}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Release Notes

Published changelog entries.

GET /release-notes

List release notes

Parameters

search
query
string

Partial-match search.

published
query
boolean

When `true`, only published release notes; when `false`, only drafts.

tag
query
string

Filter by exact tag title.

sort_by
query
string default 'created_at'
created_at updated_at title published_at
sort_direction
query
string default 'desc'
asc desc
per_page
query
integer default 15

Items per page.

page
query
integer default 1

Page number.

Responses

200 Paginated list of release notes.
401 Missing or invalid API token.

Request

curl "http://feedbackpilgrim.com/api/public/v1/release-notes" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

200 application/json
{
    "data": [
        {
            "id": 1,
            "client_id": 1,
            "user_id": 1,
            "title": "string",
            "content": "string",
            "slug": "string",
            "status": "string",
            "published_at": "2026-06-15T10:00:00Z",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "tags": [],
            "votes": [],
            "comments": []
        }
    ],
    "links": {
        "first": "string",
        "last": "string",
        "prev": "string",
        "next": "string"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "string",
        "per_page": 1,
        "to": 1,
        "total": 1
    }
}
POST /release-notes

Create a release note

Creates a release note. The `status` is set to `draft` and a `slug` is generated automatically from the title.

Body parameters required

title required
string
content required
string
tags
integer[]

Tag IDs belonging to your client.

Responses

201 Release note created.
401 Missing or invalid API token.
422 The request failed validation.

Request

curl -X POST "http://feedbackpilgrim.com/api/public/v1/release-notes" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "title": "Version 2.1.0",
    "content": "## What's New\n- Dark mode\n- Performance improvements",
    "tags": [
        1
    ]
}'

Response

201 application/json
{
    "id": 1,
    "client_id": 1,
    "user_id": 1,
    "title": "string",
    "content": "string",
    "slug": "string",
    "status": "string",
    "published_at": "2026-06-15T10:00:00Z",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "tags": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ],
    "comments": [
        {
            "id": 1,
            "content": "string"
        }
    ]
}
GET /release-notes/{release_note}

Get a release note

Parameters

release_note
path · required
integer

Release note ID.

Responses

200 The release note, including votes and comments.
401 Missing or invalid API token.
404 Resource not found within your client scope.

Request

curl "http://feedbackpilgrim.com/api/public/v1/release-notes/{release_note}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

200 application/json
{
    "id": 1,
    "client_id": 1,
    "user_id": 1,
    "title": "string",
    "content": "string",
    "slug": "string",
    "status": "string",
    "published_at": "2026-06-15T10:00:00Z",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "tags": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ],
    "comments": [
        {
            "id": 1,
            "content": "string"
        }
    ]
}
PATCH /release-notes/{release_note}

Update a release note

Parameters

release_note
path · required
integer

Release note ID.

Body parameters required

title
string
content
string
tags
integer[]

Tag IDs belonging to your client.

Responses

200 Updated release note.
401 Missing or invalid API token.
404 Resource not found within your client scope.
422 The request failed validation.

Request

curl -X PATCH "http://feedbackpilgrim.com/api/public/v1/release-notes/{release_note}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "title": "Version 2.1.1"
}'

Response

200 application/json
{
    "id": 1,
    "client_id": 1,
    "user_id": 1,
    "title": "string",
    "content": "string",
    "slug": "string",
    "status": "string",
    "published_at": "2026-06-15T10:00:00Z",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "tags": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ],
    "comments": [
        {
            "id": 1,
            "content": "string"
        }
    ]
}
DELETE /release-notes/{release_note}

Delete a release note (not supported)

Deleting release notes via the public API is not supported and always returns `405 Method Not Allowed`.

Parameters

release_note
path · required
integer

Release note ID.

Responses

401 Missing or invalid API token.
405 Operation not supported.

Request

curl -X DELETE "http://feedbackpilgrim.com/api/public/v1/release-notes/{release_note}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Contacts

Customer contacts.

GET /contacts

List contacts

Parameters

search
query
string

Partial-match search.

tag
query
string

Filter by exact tag title.

sort_by
query
string default 'created_at'
created_at updated_at name email mrr ltv
sort_direction
query
string default 'desc'
asc desc
per_page
query
integer default 15

Items per page.

page
query
integer default 1

Page number.

Responses

200 Paginated list of contacts.
401 Missing or invalid API token.

Request

curl "http://feedbackpilgrim.com/api/public/v1/contacts" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

200 application/json
{
    "data": [
        {
            "id": 1,
            "uuid": "string",
            "user_id": 1,
            "client_id": 1,
            "name": "string",
            "email": "[email protected]",
            "notes": "string",
            "avatar": "string",
            "mrr": 1,
            "ltv": 1,
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "tags": [],
            "votes": []
        }
    ],
    "links": {
        "first": "string",
        "last": "string",
        "prev": "string",
        "next": "string"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "string",
        "per_page": 1,
        "to": 1,
        "total": 1
    }
}
POST /contacts

Create or update a contact

Creates a contact. If a contact with the same email already exists for your client, that record is updated instead (returns `200`). Any properties beyond the documented fields are stored as custom metadata and returned flattened onto the contact object.

Body parameters required

name required
string
email required
string · email
avatar
string · uri
mrr
number
ltv
number
tags
integer[]

Tag IDs belonging to your client.

any

Additional custom properties are accepted and returned.

Responses

200 Existing contact updated.
201 Contact created.
401 Missing or invalid API token.
422 The request failed validation.

Request

curl -X POST "http://feedbackpilgrim.com/api/public/v1/contacts" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Jane Smith",
    "email": "[email protected]",
    "mrr": 149.99,
    "ltv": 1800,
    "avatar": "https://example.com/jane.jpg",
    "tags": [
        1,
        2
    ],
    "plan": "pro"
}'

Response

200 application/json
{
    "id": 1,
    "uuid": "string",
    "user_id": 1,
    "client_id": 1,
    "name": "string",
    "email": "[email protected]",
    "notes": "string",
    "avatar": "string",
    "mrr": 1,
    "ltv": 1,
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "tags": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ]
}
GET /contacts/{contact}

Get a contact

Parameters

contact
path · required
integer

Contact ID.

Responses

200 The contact, including tags and votes.
401 Missing or invalid API token.
404 Resource not found within your client scope.

Request

curl "http://feedbackpilgrim.com/api/public/v1/contacts/{contact}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

200 application/json
{
    "id": 1,
    "uuid": "string",
    "user_id": 1,
    "client_id": 1,
    "name": "string",
    "email": "[email protected]",
    "notes": "string",
    "avatar": "string",
    "mrr": 1,
    "ltv": 1,
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "tags": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ]
}
PATCH /contacts/{contact}

Update a contact

Parameters

contact
path · required
integer

Contact ID.

Body parameters required

name
string
email
string · email
avatar
string · uri
mrr
number
ltv
number
tags
integer[]

Tag IDs belonging to your client.

any

Additional custom properties are accepted and returned.

Responses

200 Updated contact.
401 Missing or invalid API token.
404 Resource not found within your client scope.
422 The request failed validation.

Request

curl -X PATCH "http://feedbackpilgrim.com/api/public/v1/contacts/{contact}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Jane S.",
    "mrr": 199
}'

Response

200 application/json
{
    "id": 1,
    "uuid": "string",
    "user_id": 1,
    "client_id": 1,
    "name": "string",
    "email": "[email protected]",
    "notes": "string",
    "avatar": "string",
    "mrr": 1,
    "ltv": 1,
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "tags": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ]
}

Testimonials

Customer testimonials.

GET /testimonials

List testimonials

Lists testimonials. When `approved` is omitted, only pending (not-yet-approved) testimonials are returned.

Parameters

search
query
string

Partial-match search.

approved
query
boolean

When `true`, only approved testimonials; when `false` or omitted, only pending.

rating
query
integer

Filter by exact rating (1–5).

sort_by
query
string default 'id'
created_at updated_at rating approved_at
sort_direction
query
string default 'desc'
asc desc
per_page
query
integer default 15

Items per page.

page
query
integer default 1

Page number.

Responses

200 Paginated list of testimonials.
401 Missing or invalid API token.

Request

curl "http://feedbackpilgrim.com/api/public/v1/testimonials" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

200 application/json
{
    "data": [
        {
            "id": 1,
            "client_id": 1,
            "contact_id": 1,
            "title": "string",
            "description": "string",
            "rating": 1,
            "avatar_image": "string",
            "username": "string",
            "subtitle": "string",
            "approved_at": "2026-06-15T10:00:00Z",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "contact": {
                "id": 1,
                "uuid": "string",
                "user_id": 1,
                "client_id": 1,
                "name": "string",
                "email": "[email protected]",
                "notes": "string",
                "avatar": "string",
                "mrr": 1,
                "ltv": 1,
                "created_at": "2026-06-15T10:00:00Z",
                "updated_at": "2026-06-15T10:00:00Z",
                "tags": [],
                "votes": []
            },
            "votes": [],
            "comments": []
        }
    ],
    "links": {
        "first": "string",
        "last": "string",
        "prev": "string",
        "next": "string"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "string",
        "per_page": 1,
        "to": 1,
        "total": 1
    }
}
POST /testimonials

Create a testimonial

Body parameters required

description required
string
rating
integer
username required
string
contact_id
integer

ID of a contact belonging to your client.

Responses

201 Testimonial created.
401 Missing or invalid API token.
422 The request failed validation.

Request

curl -X POST "http://feedbackpilgrim.com/api/public/v1/testimonials" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "description": "Amazing product, exceeded expectations!",
    "rating": 5,
    "username": "happy_customer",
    "contact_id": 42
}'

Response

201 application/json
{
    "id": 1,
    "client_id": 1,
    "contact_id": 1,
    "title": "string",
    "description": "string",
    "rating": 1,
    "avatar_image": "string",
    "username": "string",
    "subtitle": "string",
    "approved_at": "2026-06-15T10:00:00Z",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "contact": {
        "id": 1,
        "uuid": "string",
        "user_id": 1,
        "client_id": 1,
        "name": "string",
        "email": "[email protected]",
        "notes": "string",
        "avatar": "string",
        "mrr": 1,
        "ltv": 1,
        "created_at": "2026-06-15T10:00:00Z",
        "updated_at": "2026-06-15T10:00:00Z",
        "tags": [
            {
                "id": 1,
                "client_id": 1,
                "title": "string",
                "created_at": "2026-06-15T10:00:00Z",
                "updated_at": "2026-06-15T10:00:00Z",
                "posts_count": 1,
                "contacts_count": 1
            }
        ],
        "votes": [
            {
                "id": 1,
                "contact_id": 1
            }
        ]
    },
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ],
    "comments": [
        {
            "id": 1,
            "content": "string"
        }
    ]
}
GET /testimonials/{testimonial}

Get a testimonial

Parameters

testimonial
path · required
integer

Testimonial ID.

Responses

200 The testimonial, including votes and comments.
401 Missing or invalid API token.
404 Resource not found within your client scope.

Request

curl "http://feedbackpilgrim.com/api/public/v1/testimonials/{testimonial}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

200 application/json
{
    "id": 1,
    "client_id": 1,
    "contact_id": 1,
    "title": "string",
    "description": "string",
    "rating": 1,
    "avatar_image": "string",
    "username": "string",
    "subtitle": "string",
    "approved_at": "2026-06-15T10:00:00Z",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "contact": {
        "id": 1,
        "uuid": "string",
        "user_id": 1,
        "client_id": 1,
        "name": "string",
        "email": "[email protected]",
        "notes": "string",
        "avatar": "string",
        "mrr": 1,
        "ltv": 1,
        "created_at": "2026-06-15T10:00:00Z",
        "updated_at": "2026-06-15T10:00:00Z",
        "tags": [
            {
                "id": 1,
                "client_id": 1,
                "title": "string",
                "created_at": "2026-06-15T10:00:00Z",
                "updated_at": "2026-06-15T10:00:00Z",
                "posts_count": 1,
                "contacts_count": 1
            }
        ],
        "votes": [
            {
                "id": 1,
                "contact_id": 1
            }
        ]
    },
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ],
    "comments": [
        {
            "id": 1,
            "content": "string"
        }
    ]
}
PATCH /testimonials/{testimonial}

Update a testimonial

Updates a testimonial. Set `approved_at` to approve it.

Parameters

testimonial
path · required
integer

Testimonial ID.

Body parameters required

description
string
rating
integer
username
string
approved_at
string · date-time

Set to approve the testimonial. Update only.

Responses

200 Updated testimonial.
401 Missing or invalid API token.
404 Resource not found within your client scope.
422 The request failed validation.

Request

curl -X PATCH "http://feedbackpilgrim.com/api/public/v1/testimonials/{testimonial}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "approved_at": "2026-06-15T10:00:00Z"
}'

Response

200 application/json
{
    "id": 1,
    "client_id": 1,
    "contact_id": 1,
    "title": "string",
    "description": "string",
    "rating": 1,
    "avatar_image": "string",
    "username": "string",
    "subtitle": "string",
    "approved_at": "2026-06-15T10:00:00Z",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "contact": {
        "id": 1,
        "uuid": "string",
        "user_id": 1,
        "client_id": 1,
        "name": "string",
        "email": "[email protected]",
        "notes": "string",
        "avatar": "string",
        "mrr": 1,
        "ltv": 1,
        "created_at": "2026-06-15T10:00:00Z",
        "updated_at": "2026-06-15T10:00:00Z",
        "tags": [
            {
                "id": 1,
                "client_id": 1,
                "title": "string",
                "created_at": "2026-06-15T10:00:00Z",
                "updated_at": "2026-06-15T10:00:00Z",
                "posts_count": 1,
                "contacts_count": 1
            }
        ],
        "votes": [
            {
                "id": 1,
                "contact_id": 1
            }
        ]
    },
    "votes": [
        {
            "id": 1,
            "contact_id": 1
        }
    ],
    "comments": [
        {
            "id": 1,
            "content": "string"
        }
    ]
}
DELETE /testimonials/{testimonial}

Delete a testimonial (not supported)

Deleting testimonials via the public API is not supported and always returns `405 Method Not Allowed`.

Parameters

testimonial
path · required
integer

Testimonial ID.

Responses

401 Missing or invalid API token.
405 Operation not supported.

Request

curl -X DELETE "http://feedbackpilgrim.com/api/public/v1/testimonials/{testimonial}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Tags

Reusable labels for posts and contacts.

GET /tags

List tags

Lists tags with usage counts (`posts_count`, `contacts_count`).

Parameters

search
query
string

Partial-match search.

sort_by
query
string default 'title'
title created_at updated_at
sort_direction
query
string default 'asc'
asc desc
per_page
query
integer default 15

Items per page.

page
query
integer default 1

Page number.

Responses

200 Paginated list of tags.
401 Missing or invalid API token.

Request

curl "http://feedbackpilgrim.com/api/public/v1/tags" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

200 application/json
{
    "data": [
        {
            "id": 1,
            "client_id": 1,
            "title": "string",
            "created_at": "2026-06-15T10:00:00Z",
            "updated_at": "2026-06-15T10:00:00Z",
            "posts_count": 1,
            "contacts_count": 1
        }
    ],
    "links": {
        "first": "string",
        "last": "string",
        "prev": "string",
        "next": "string"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "string",
        "per_page": 1,
        "to": 1,
        "total": 1
    }
}
POST /tags

Create a tag

Body parameters required

title required
string

Unique per client.

Responses

201 Tag created.
401 Missing or invalid API token.
422 The request failed validation.

Request

curl -X POST "http://feedbackpilgrim.com/api/public/v1/tags" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "title": "feature"
}'

Response

201 application/json
{
    "id": 1,
    "client_id": 1,
    "title": "string",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "posts_count": 1,
    "contacts_count": 1
}
PATCH /tags/{tag}

Update a tag

Parameters

tag
path · required
integer

Tag ID.

Body parameters required

title required
string

Unique per client.

Responses

200 Updated tag.
401 Missing or invalid API token.
404 Resource not found within your client scope.
422 The request failed validation.

Request

curl -X PATCH "http://feedbackpilgrim.com/api/public/v1/tags/{tag}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "title": "enhancement"
}'

Response

200 application/json
{
    "id": 1,
    "client_id": 1,
    "title": "string",
    "created_at": "2026-06-15T10:00:00Z",
    "updated_at": "2026-06-15T10:00:00Z",
    "posts_count": 1,
    "contacts_count": 1
}
DELETE /tags/{tag}

Delete a tag

Deletes a tag. Any associations to posts and contacts are detached first.

Parameters

tag
path · required
integer

Tag ID.

Responses

204 Tag deleted.
401 Missing or invalid API token.
404 Resource not found within your client scope.

Request

curl -X DELETE "http://feedbackpilgrim.com/api/public/v1/tags/{tag}" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

MCP server

The Model Context Protocol (MCP) server lets AI agents work with your Feedback Pilgrim data through the same logic as the REST API — it is just another transport. Every tool is scoped to the client of the Sanctum token you authenticate with; you never pass a client_id.

Connecting

Point your MCP client at http://feedbackpilgrim.com/mcp over streamable HTTP and authenticate with the same bearer token used for the REST API. The endpoint is stateless and bearer-only; session cookies are rejected.

Client configuration
{
    "mcpServers": {
        "feedback-pilgrim": {
            "type": "http",
            "url": "http://feedbackpilgrim.com/mcp",
            "headers": {
                "Authorization": "Bearer YOUR_API_TOKEN"
            }
        }
    }
}

Request

{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "list_posts",
        "arguments": {
            "per_page": 2,
            "status": "pending"
        }
    }
}

Response

200 application/json
{
    "records": [
        {
            "id": 12,
            "title": "Dark mode",
            "status": "pending"
        }
    ],
    "pagination": {
        "page": 1,
        "per_page": 2,
        "total": 1,
        "has_more": false
    }
}

Response

error application/json
{
    "content": [
        {
            "type": "text",
            "text": "Resource not found."
        }
    ],
    "isError": true
}

Tools

List tools return a paginated envelope (records + pagination); get tools take an id.

list_posts tool

List feedback posts for the authenticated client, with pagination, search, status/tag filters, and sorting. Returns a paginated envelope of posts (title, content, status, tags, contact, votes). Use to browse or find feature requests and feedback.

page
integer

Page number to retrieve. Example: 1.

per_page
integer

Records per page (max 100, default 15). Example: 25.

search
string

Case-insensitive match against title and content. Example: "dark mode".

status
string
pending in_progress completed

Filter by workflow status.

tag
string

Filter to posts carrying this tag title. Example: "bug".

published
boolean

true returns only published posts, false only unpublished.

sort_by
string
created_at updated_at title status published_at

Column to sort by. Default created_at.

sort_direction
string
asc desc

Sort direction. Default desc.

get_post tool

Fetch a single feedback post by id for the authenticated client, including contact, tags, votes, and comments. Returns not-found if the post belongs to another client. Use to inspect one post in detail.

id required
integer

The post id to retrieve. Example: 42.

create_post tool

Create a feedback post for the authenticated client. Not idempotent — calling again creates another post, so avoid blind retries. Returns the created post with tags and contact.

title required
string

Post title. Example: "Add dark mode".

content required
string

Post body. Example: "Users want a dark theme."

status
string
pending in_progress completed

Workflow status. Defaults to pending.

board_id
integer

Board id to file the post under. Must belong to your client. Defaults to the client's first board.

tags
array

Tag ids to attach. Must belong to your client. Example: [3, 8].

update_post tool

Update an existing feedback post by id for the authenticated client. Only supplied fields change. Returns not-found if the post belongs to another client.

id required
integer

The post id to update. Example: 42.

title
string

New title.

content
string

New body.

status
string
pending in_progress completed

New workflow status.

board_id
integer

Move the post to this board. Must belong to your client.

tags
array

Replacement tag ids (sync). Must belong to your client.

list_release_notes tool

List release notes for the authenticated client, with pagination, search, published filter, tag filter, and sorting. Returns a paginated envelope (title, content, slug, status, tags). Use to browse the changelog.

page
integer

Page number to retrieve. Example: 1.

per_page
integer

Records per page (max 100, default 15). Example: 25.

search
string

Case-insensitive match against title and content. Example: "v2".

published
boolean

true returns only published notes, false only drafts.

tag
string

Filter to release notes carrying this tag title.

sort_by
string
created_at updated_at title published_at

Column to sort by. Default created_at.

sort_direction
string
asc desc

Sort direction. Default desc.

get_release_note tool

Fetch a single release note by id for the authenticated client, including tags, votes, and comments. Returns not-found if it belongs to another client.

id required
integer

The release note id to retrieve. Example: 7.

create_release_note tool

Create a release note for the authenticated client. It starts as a draft with a date-suffixed slug and is authored by the token owner. Not idempotent — avoid blind retries.

title required
string

Release note title. Example: "v2.1 released".

content required
string

Release note body (markdown allowed).

tags
array

Tag ids to attach. Must belong to your client.

update_release_note tool

Update an existing release note by id for the authenticated client. Only supplied fields change. Returns not-found if it belongs to another client.

id required
integer

The release note id to update. Example: 7.

title
string

New title.

content
string

New body.

tags
array

Replacement tag ids (sync). Must belong to your client.

list_contacts tool

List customer contacts for the authenticated client, with pagination, search, tag filter, and sorting. Custom metadata fields are flattened onto each record. Use to browse or find the people who submit feedback.

page
integer

Page number to retrieve. Example: 1.

per_page
integer

Records per page (max 100, default 15). Example: 25.

search
string

Case-insensitive match against name and email. Example: "acme".

tag
string

Filter to contacts carrying this tag title. Example: "premium".

sort_by
string
created_at updated_at name email mrr ltv

Column to sort by. Default created_at.

sort_direction
string
asc desc

Sort direction. Default desc.

get_contact tool

Fetch a single contact by id for the authenticated client, including tags and votes, with custom metadata fields flattened onto the record. Returns not-found if it belongs to another client.

id required
integer

The contact id to retrieve. Example: 12.

create_contact tool

Create or update a contact for the authenticated client, matched by email (upsert). Custom fields beyond the documented ones are stored as metadata. The response includes was_created (true if a new contact was made, false if an existing one was updated).

name required
string

Contact name. Example: "Jane Doe".

email required
string

Contact email; the upsert key. Example: "[email protected]".

avatar
string

Avatar URL.

mrr
number

Monthly recurring revenue.

ltv
number

Lifetime value.

tags
array

Tag ids to attach. Must belong to your client.

update_contact tool

Update an existing contact by id for the authenticated client. Only supplied fields change. Returns not-found if it belongs to another client.

id required
integer

The contact id to update. Example: 12.

name
string

New name.

email
string

New email (unique per client).

avatar
string

New avatar URL.

mrr
number

Monthly recurring revenue.

ltv
number

Lifetime value.

tags
array

Replacement tag ids (sync). Must belong to your client.

list_testimonials tool

List testimonials for the authenticated client, with pagination, search, rating filter, and sorting. Note: when the approved filter is omitted, only pending testimonials are returned; pass approved=true for approved ones. Use to browse social proof.

page
integer

Page number to retrieve. Example: 1.

per_page
integer

Records per page (max 100, default 15). Example: 25.

search
string

Case-insensitive match against description and username.

approved
boolean

true returns approved testimonials; omit to return only pending.

rating
integer

Filter by exact star rating, 1-5.

sort_by
string
created_at updated_at rating approved_at

Column to sort by.

sort_direction
string
asc desc

Sort direction. Default desc.

get_testimonial tool

Fetch a single testimonial by id for the authenticated client, including contact, votes, and comments. Returns not-found if it belongs to another client.

id required
integer

The testimonial id to retrieve. Example: 3.

create_testimonial tool

Create a testimonial for the authenticated client. New testimonials are unapproved until approved elsewhere. Not idempotent — avoid blind retries.

description required
string

Testimonial text. Example: "Best tool we use."

username required
string

Display name of the author. Example: "Jane @ Acme".

rating
integer

Star rating, 1-5.

contact_id
integer

Optional contact id to link; must belong to your client.

update_testimonial tool

Update an existing testimonial by id for the authenticated client. Set approved_at to approve it. Only supplied fields change. Returns not-found if it belongs to another client.

id required
integer

The testimonial id to update. Example: 3.

description
string

New testimonial text.

username
string

New display name.

rating
integer

Star rating, 1-5.

approved_at
string

ISO date/time to approve the testimonial; omit to leave pending.

list_tags tool

List tags for the authenticated client, with pagination, search, and sorting. Each tag includes counts of posts and contacts. Use to discover available tag titles before filtering other resources by tag.

page
integer

Page number to retrieve. Example: 1.

per_page
integer

Records per page (max 100, default 15). Example: 25.

search
string

Case-insensitive match against tag title. Example: "bug".

sort_by
string
title created_at updated_at

Column to sort by. Default title.

sort_direction
string
asc desc

Sort direction. Default asc.

create_tag tool

Create a tag for the authenticated client. Titles are unique per client. Not idempotent — avoid blind retries.

title required
string

Tag title, unique within your client. Example: "bug".

update_tag tool

Rename a tag by id for the authenticated client. The new title must be unique within your client. Returns not-found if it belongs to another client.

id required
integer

The tag id to update. Example: 9.

title required
string

New tag title, unique within your client.

delete_tag tool

Delete a tag by id for the authenticated client. The tag is detached from all posts and contacts, then removed. Returns not-found if it belongs to another client. This is the only delete operation the API exposes.

id required
integer

The tag id to delete. Example: 9.

Schemas

The object shapes returned by the API.

Error

message
string

ValidationError

message
string
errors
object

Pagination

data
any[]
links
object
meta
object

Tag

id
integer
client_id
integer
title
string
created_at
string · date-time
updated_at
string · date-time
posts_count
integer

Present on list responses only.

contacts_count
integer

Present on list responses only.

Vote

A vote on a post, release note, or testimonial.

id
integer
contact_id
integer nullable
any

Additional custom properties are accepted and returned.

Comment

A comment on a post, release note, or testimonial.

id
integer
content
string
any

Additional custom properties are accepted and returned.

Post

id
integer
client_id
integer
stage_id
integer nullable
board_id
integer nullable
contact_id
integer nullable
title
string
content
string nullable
notes
string nullable
status
string nullable
pending in_progress completed
stage_position
integer nullable
published_at
string · date-time nullable
archived_at
string · date-time nullable
created_at
string · date-time
updated_at
string · date-time
contact
object nullable
tags
object[]
votes
object[]
comments
object[]

Present on single-post responses only.

ReleaseNote

id
integer
client_id
integer
user_id
integer
title
string
content
string
slug
string
status
string nullable

Set to `draft` on creation.

published_at
string · date-time nullable
created_at
string · date-time
updated_at
string · date-time
tags
object[]
votes
object[]
comments
object[]

Contact

Custom metadata fields are returned flattened onto this object alongside the documented properties.

id
integer
uuid
string
user_id
integer nullable
client_id
integer
name
string nullable
email
string · email nullable
notes
string nullable
avatar
string nullable
mrr
number nullable
ltv
number nullable
created_at
string · date-time
updated_at
string · date-time
tags
object[]
votes
object[]
any

Additional custom properties are accepted and returned.

Testimonial

id
integer
client_id
integer
contact_id
integer nullable
title
string nullable
description
string
rating
integer nullable
avatar_image
string nullable
username
string nullable
subtitle
string nullable
approved_at
string · date-time nullable
created_at
string · date-time
updated_at
string · date-time
contact
object nullable
votes
object[]
comments
object[]

Present on single-testimonial responses only.

InitResponse

auth_url
string · uri

Returned when a contact with an email was supplied.

any

Additional custom properties are accepted and returned.