API
Push content to your gitmoreviews site from your own system. The first surface is blog ingestion: your software writes the articles — from completed jobs, seasonal campaigns, whatever you know about your customers — and delivers them here. Posts appear on your live site and in its sitemap immediately.
Authentication
Create a token in Dashboard → Settings → API tokens (account owner only). The secret starts with gmv_ and is shown exactly once — we store only a hash. Send it as a bearer token on every request:
curl https://gitmoreviews.com/api/v1/websites \
-H "Authorization: Bearer gmv_your_token_here"A token is scoped to your whole account: it can read and write every site the account owns. Revoke it from the same settings page — revocation is immediate.
Errors & limits
Every non-2xx response uses one JSON envelope:
{
"error": {
"code": "validation_failed",
"message": "The post payload is invalid.",
"issues": [{ "path": "paragraphs", "message": "at least one paragraph" }]
}
}Codes you'll meet: unauthorized (401), not_found (404), method_not_allowed (405), site_not_generated (409), validation_failed (422, with issues), and rate_limited (429). Each token may make 120 requests per minute.
List your websites
GET/api/v1/websites
Returns the account's sites. Use the id in the blog endpoints below.
{
"websites": [
{ "id": "cmc1x…", "subdomain": "scruffy-city-plumbing", "status": "PUBLISHED" }
]
}List posts
GET/api/v1/websites/:id/posts
All of a site's blog posts, newest first, in the same shape you push them.
Create or update a post
POST/api/v1/websites/:id/posts
Upserts by slug: a new slug creates the post (201), an existing slug replaces it (200) — so re-pushing an edited article just works.
curl -X POST https://gitmoreviews.com/api/v1/websites/WEBSITE_ID/posts \
-H "Authorization: Bearer gmv_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"slug": "spring-ac-tune-up",
"title": "Why a spring AC tune-up beats a July breakdown",
"description": "What our techs check in a 21-point spring tune-up.",
"publishedAt": "2026-07-11",
"paragraphs": [
"Every summer we meet the same emergency: a capacitor that gave out on the hottest day of the year.",
"A spring tune-up catches it for a fraction of the cost."
],
"heroImageUrl": "https://example.com/images/tune-up.jpg",
"relatedTradeSlugs": ["hvac"],
"relatedAreaSlugs": ["knoxville"]
}'Field rules:
slug— lowercase letters, digits, hyphens; the post's URL (/blog/<slug>).title,description— required; the description doubles as the meta description.publishedAt— optional ISO date; defaults to today.paragraphs— at least one plain-text paragraph.heroImageUrl— optional; an https URL or a site-relative path.relatedTradeSlugs/relatedAreaSlugs— optional; must match the site's own trade/area slugs (unknown slugs are a 422, so typos can't silently drop your internal links).
Delete a post
DELETE/api/v1/websites/:id/posts/:slug
curl -X DELETE https://gitmoreviews.com/api/v1/websites/WEBSITE_ID/posts/spring-ac-tune-up \
-H "Authorization: Bearer gmv_your_token_here"Returns { "deleted": true }; deleting a slug that doesn't exist is a 404.