Feedback API
Request features, report issues and upvote what matters to you. 14 ops: list_feedback, get_feedback, list_my_feedback, request_feature, report_issue, upvote_feedback, remove_feedback_vote, comment_on_feedback, set_feedback_subscription, submit_review, list_reviews, update_feedback, respond_to_feedba
Request features, report issues and upvote what matters to you.
List feature requests and issues · POST /api/v1/list_feedback · scope feedback:read or GET …?input=
The Gutlog feedback board: feature requests every customer can see, plus your own issue reports (and ones the team published), with status and upvotes, most upvoted first. Each item says whether your organization voted for it or filed it. Call it before request_feature or report_issue to find an existing item to upvote instead of filing a duplicate, or when the human asks what is planned. Works without a credential (public items only).
curl -X POST https://getgutlog.com/api/v1/list_feedback \ -H "Authorization: Bearer gutlog_…"npx @meterapp/gutlog list_feedback{
"type": "object",
"properties": {
"kind": {
"default": "all",
"description": "feature = feature requests, issue = bug reports (yours, and ones the team published).",
"type": "string",
"enum": [
"feature",
"issue",
"all"
]
},
"status": {
"default": "active",
"description": "active = open, planned, in_progress.",
"type": "string",
"enum": [
"active",
"all",
"open",
"planned",
"in_progress",
"done",
"declined",
"duplicate"
]
},
"sort": {
"default": "top",
"description": "top = most upvoted, new = most recent, recent_activity = latest vote, comment or status change.",
"type": "string",
"enum": [
"top",
"new",
"recent_activity"
]
},
"q": {
"description": "Words to find in the title.",
"type": "string",
"maxLength": 100
},
"mine": {
"default": false,
"description": "Only items your organization filed.",
"type": "boolean"
},
"limit": {
"default": 20,
"description": "Page size, at most 100.",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"offset": {
"default": 0,
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"cursor": {
"description": "next_cursor from the previous page (same as offset).",
"type": "string",
"pattern": "^\\d+$"
}
}
}Get a feature request or issue · POST /api/v1/get_feedback · scope feedback:read or GET …?input=
One feedback item with its status, upvotes, comments (oldest first; official answers from the Gutlog team are marked `official`) and its timeline of status changes with the team's notes. Your own issues include the context you attached.
curl -X POST https://getgutlog.com/api/v1/get_feedback \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"id":1}'npx @meterapp/gutlog get_feedback --json '{"id":1}'{
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "The item's id from list_feedback, request_feature or report_issue (e.g. 42)."
}
},
"required": [
"id"
]
}list_my_feedback
readList my feedback and subscriptions · POST /api/v1/list_my_feedback · scope feedback:read or GET …?input=
What your organization filed (every status), the items you get email about (filed, upvoted, commented, followed) with whether you muted them, your organization's review, and whether feedback email reaches you. Use it to follow up on earlier reports.
curl -X POST https://getgutlog.com/api/v1/list_my_feedback \ -H "Authorization: Bearer gutlog_…"npx @meterapp/gutlog list_my_feedback{
"type": "object",
"properties": {}
}request_feature
writeRequest a feature · POST /api/v1/request_feature · scope feedback:write
Files a feature request on the Gutlog board and upvotes it for your organization. Use it when the human wishes Gutlog did something it cannot do yet (an integration, an op, a Meta feature, a dashboard view). It checks for duplicates first: an identical request gets your vote instead, and when likely matches exist nothing is filed and `similar` lists them (filed: false): upvote_feedback the match, or call again with force: true if yours is different. 10 new items per organization a day. The person behind the call gets a thank-you email and one at every status change. Feature requests and comments are public (never who wrote them beyond a first name): no API keys, message content or customer data.
curl -X POST https://getgutlog.com/api/v1/request_feature \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"title":"Let me log a recipe once and reuse it"}'npx @meterapp/gutlog request_feature --json '{"title":"Let me log a recipe once and reuse it"}'{
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 3,
"maxLength": 140,
"description": "What you want, in one line."
},
"details": {
"default": "",
"description": "Why you need it and what you are building; concrete examples help it get planned.",
"type": "string",
"maxLength": 5000
},
"body": {
"description": "Alias of details.",
"type": "string",
"maxLength": 5000
},
"force": {
"default": false,
"description": "File even when similar items exist.",
"type": "boolean"
}
},
"required": [
"title"
]
}report_issue
writeReport an issue · POST /api/v1/report_issue · scope feedback:write
Reports a problem with Gutlog itself: a failing or wrong call (pass the request_id from the error or the X-Request-Id header, and the op), a meal that matched the wrong food or got the wrong nutrients, a barcode that was not found, a docs error. Attach context (meal_id, program_id, gtin, the error), never what the person ate or how they feel, so the team can reproduce it; ids are checked against your organization. Issues are private: only your organization and the Gutlog team see them, and the team may publish a sanitized title so others can upvote it. Upvote a matching report from list_feedback (kind issue) instead of filing again; likely duplicates are returned in `similar` with filed: false unless force: true. 10 new items per organization a day. The reporter gets an email with what was captured and one at every status change.
curl -X POST https://getgutlog.com/api/v1/report_issue \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"title":"Let me log a recipe once and reuse it"}'npx @meterapp/gutlog report_issue --json '{"title":"Let me log a recipe once and reuse it"}'{
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 3,
"maxLength": 140,
"description": "What is wrong, in one line."
},
"details": {
"default": "",
"description": "What you did, what you expected and what happened (status, error code, format).",
"type": "string",
"maxLength": 5000
},
"body": {
"description": "Alias of details.",
"type": "string",
"maxLength": 5000
},
"request_id": {
"description": "The request_id of the failing call (shortcut for context.request_id).",
"type": "string",
"maxLength": 128
},
"op": {
"description": "The op the failing call used, e.g. log_meal (shortcut for context.op).",
"type": "string",
"maxLength": 80
},
"context": {
"description": "Gutlog identifiers for what failed: request_id, op, meal_id, program_id, gtin, status, error_code, error, client. Never shown publicly; at most 128 KB.",
"type": "object",
"properties": {
"request_id": {
"description": "The request_id of the failing call (X-Request-Id header, or request_id in the error).",
"type": "string",
"pattern": "^[A-Za-z0-9._:-]{1,128}$"
},
"op": {
"description": "The op or endpoint that failed, e.g. log_meal.",
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,79}$"
},
"meal_id": {
"description": "The meal involved (meals.id); must be one of your organization's.",
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"program_id": {
"description": "The elimination program involved; must be one of your organization's.",
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"gtin": {
"description": "The barcode involved (products are public data).",
"type": "string",
"pattern": "^[0-9]{8,14}$"
},
"locale": {
"description": "The language involved, e.g. pt_BR.",
"type": "string",
"pattern": "^[A-Za-z]{2,8}([-_][A-Za-z0-9]{1,8})*$"
},
"status": {
"description": "The HTTP status the call returned.",
"type": "integer",
"minimum": 100,
"maximum": 599
},
"error_code": {
"description": "The error code, e.g. daily_limit_reached.",
"type": "string",
"maxLength": 100
},
"error": {
"description": "The error message as the client saw it (no keys, no food or symptom text).",
"type": "string",
"maxLength": 2000
},
"client": {
"description": "Client and version, e.g. gutlog-cli/0.5.0 or Claude Code.",
"type": "string",
"maxLength": 100
},
"version": {
"type": "string",
"maxLength": 50
},
"extra": {
"description": "Anything else that helps reproduce it (no secrets, no health data).",
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
},
"additionalProperties": false
},
"force": {
"default": false,
"description": "File even when similar reports exist.",
"type": "boolean"
}
},
"required": [
"title"
]
}upvote_feedback
writeUpvote a feature request or issue · POST /api/v1/upvote_feedback · scope feedback:write
Adds your organization's upvote to a feature request or issue ("me too"); votes decide what gets built and fixed first, and you get an email when its status changes. Idempotent: one vote per organization. A vote on a duplicate goes to the original. Returns the item with its new vote count.
curl -X POST https://getgutlog.com/api/v1/upvote_feedback \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"id":1}'npx @meterapp/gutlog upvote_feedback --json '{"id":1}'{
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "The item's id from list_feedback, request_feature or report_issue (e.g. 42)."
}
},
"required": [
"id"
]
}remove_feedback_vote
writeRemove an upvote · POST /api/v1/remove_feedback_vote · scope feedback:write
Takes back your organization's upvote on a feature request or issue, and stops its emails unless you filed or commented on it. Returns the item with its new vote count.
curl -X POST https://getgutlog.com/api/v1/remove_feedback_vote \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"id":1}'npx @meterapp/gutlog remove_feedback_vote --json '{"id":1}'{
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "The item's id from list_feedback, request_feature or report_issue (e.g. 42)."
}
},
"required": [
"id"
]
}comment_on_feedback
writeComment on a feature request or issue · POST /api/v1/comment_on_feedback · scope feedback:write
Adds context to an existing feature request or issue: your use case, another failing request, a workaround. Prefer it (with upvote_feedback) over filing a near-duplicate. You then get emails about the item; its author gets a daily digest of new comments. 50 comments per organization a day. Feature requests and comments are public (never who wrote them beyond a first name): no API keys, message content or customer data.
curl -X POST https://getgutlog.com/api/v1/comment_on_feedback \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"id":1,"body":"I cook the same chili every week and re-enter it each time."}'npx @meterapp/gutlog comment_on_feedback --json '{"id":1,"body":"I cook the same chili every week and re-enter it each time."}'{
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "The item's id from list_feedback, request_feature or report_issue (e.g. 42)."
},
"body": {
"type": "string",
"minLength": 1,
"maxLength": 5000,
"description": "The comment."
}
},
"required": [
"id",
"body"
]
}Start or stop feedback emails · POST /api/v1/set_feedback_subscription · scope feedback:write
With id: start or stop emails about one feature request or issue. Without id: turn every feedback email (thank-yous, status changes, replies) on or off for the person behind this credential. Lifecycle and product emails are separate.
curl -X POST https://getgutlog.com/api/v1/set_feedback_subscription \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"subscribed":false}'npx @meterapp/gutlog set_feedback_subscription --json '{"subscribed":false}'{
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "The item's id from list_feedback, request_feature or report_issue (e.g. 42)."
},
"subscribed": {
"type": "boolean",
"description": "true to get emails, false to stop them."
}
},
"required": [
"subscribed"
]
}submit_review
writePost or edit a review · POST /api/v1/submit_review · scope feedback:write
Posts your organization's public review of Gutlog (1–5 stars, what you like, what you don't, what you use it for), or edits it (once an hour; earlier versions are kept). Ask the human for the rating and words; never invent a review or post one they did not approve. It publishes on /reviews right away unless an automated check holds it for a quick look (new accounts, links, profanity). marketing_consent: true lets Meter quote it. The reviewer gets a thank-you email and one when the team replies.
curl -X POST https://getgutlog.com/api/v1/submit_review \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"rating":1}'npx @meterapp/gutlog submit_review --json '{"rating":1}'{
"type": "object",
"properties": {
"rating": {
"type": "integer",
"minimum": 1,
"maximum": 5,
"description": "1 (poor) to 5 (excellent)."
},
"title": {
"default": "",
"description": "One-line summary.",
"type": "string",
"maxLength": 120
},
"body": {
"default": "",
"description": "The review.",
"type": "string",
"maxLength": 2000
},
"likes": {
"default": "",
"description": "What works well.",
"type": "string",
"maxLength": 1000
},
"dislikes": {
"default": "",
"description": "What should be better.",
"type": "string",
"maxLength": 1000
},
"use_case": {
"default": "",
"description": "What you use Gutlog for.",
"type": "string",
"maxLength": 200
},
"display_name": {
"description": "Name shown with the review; defaults to your first name.",
"type": "string",
"maxLength": 60
},
"display_company": {
"description": "Company shown with the review, if any.",
"type": "string",
"maxLength": 80
},
"marketing_consent": {
"default": false,
"description": "May Meter quote this review on the site and in marketing.",
"type": "boolean"
}
},
"required": [
"rating"
]
}List reviews · POST /api/v1/list_reviews · scope feedback:read or GET …?input=
Published reviews of Gutlog with the aggregate (average rating, count and distribution) and the team's responses. Works without a credential.
curl -X POST https://getgutlog.com/api/v1/list_reviews \ -H "Authorization: Bearer gutlog_…"npx @meterapp/gutlog list_reviews{
"type": "object",
"properties": {
"sort": {
"default": "newest",
"description": "helpful = most detailed first.",
"type": "string",
"enum": [
"newest",
"helpful",
"highest",
"lowest"
]
},
"rating": {
"description": "Only reviews with this rating.",
"type": "integer",
"minimum": 1,
"maximum": 5
},
"status": {
"default": "published",
"description": "Gutlog team only: held or hidden reviews too.",
"type": "string",
"enum": [
"published",
"pending",
"hidden",
"all"
]
},
"limit": {
"default": 20,
"type": "integer",
"minimum": 1,
"maximum": 100
},
"offset": {
"default": 0,
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
}
}update_feedback
writeUpdate feedback (staff) · POST /api/v1/update_feedback · scope feedback:write
Gutlog team only. Moves an item through open → planned → in_progress → done, or declined, or duplicate (with duplicate_of: votes and subscribers move to the original), with a note every subscriber gets by email. Also publishes or hides an issue (visibility, with a sanitized public_title) and links the GitHub issue or PR (external_ref).
curl -X POST https://getgutlog.com/api/v1/update_feedback \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"id":1}'npx @meterapp/gutlog update_feedback --json '{"id":1}'{
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "The item's id from list_feedback, request_feature or report_issue (e.g. 42)."
},
"status": {
"type": "string",
"enum": [
"open",
"planned",
"in_progress",
"done",
"declined",
"duplicate"
]
},
"note": {
"description": "Why, or what shipped and how to use it; emailed with the status change.",
"type": "string",
"maxLength": 5000
},
"duplicate_of": {
"description": "The original, with status duplicate.",
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"external_ref": {
"description": "GitHub issue or PR URL; empty clears it.",
"anyOf": [
{
"type": "string",
"maxLength": 500,
"format": "uri"
},
{
"type": "string",
"const": ""
}
]
},
"visibility": {
"type": "string",
"enum": [
"public",
"private"
]
},
"public_title": {
"description": "Sanitized title others see for a published issue.",
"type": "string",
"maxLength": 140
}
},
"required": [
"id"
]
}respond_to_feedback
writeRespond officially (staff) · POST /api/v1/respond_to_feedback · scope feedback:write
Gutlog team only. Posts an official response on an item (emailed to every subscriber), optionally changing its status in the same call.
curl -X POST https://getgutlog.com/api/v1/respond_to_feedback \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"id":1,"body":"I cook the same chili every week and re-enter it each time."}'npx @meterapp/gutlog respond_to_feedback --json '{"id":1,"body":"I cook the same chili every week and re-enter it each time."}'{
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "The item's id from list_feedback, request_feature or report_issue (e.g. 42)."
},
"body": {
"type": "string",
"minLength": 1,
"maxLength": 5000,
"description": "The response, signed as the Gutlog team."
},
"status": {
"type": "string",
"enum": [
"open",
"planned",
"in_progress",
"done",
"declined",
"duplicate"
]
},
"note": {
"type": "string",
"maxLength": 5000
},
"duplicate_of": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"external_ref": {
"type": "string",
"maxLength": 500,
"format": "uri"
}
},
"required": [
"id",
"body"
]
}respond_to_review
writeRespond to or moderate a review (staff) · POST /api/v1/respond_to_review · scope feedback:write
Gutlog team only. Replies publicly under a review (the reviewer gets an email), and/or hides or publishes it with a reason. Never hide a review for being negative.
curl -X POST https://getgutlog.com/api/v1/respond_to_review \ -H "Authorization: Bearer gutlog_…" \ -H "Content-Type: application/json" \ -d '{"id":1}'npx @meterapp/gutlog respond_to_review --json '{"id":1}'{
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "The review id from list_reviews."
},
"response": {
"type": "string",
"minLength": 1,
"maxLength": 2000
},
"status": {
"type": "string",
"enum": [
"published",
"hidden",
"pending"
]
},
"reason": {
"description": "Why it is hidden; kept internal.",
"type": "string",
"maxLength": 300
}
},
"required": [
"id"
]
}