Cheers Public API

The Cheers API allows you to programmatically access your organization's review data, badges, taps, and more. All API endpoints require authentication via API key.

Base URLhttps://app.cheers.tech/api/public/v1

Authentication

All API requests require a Bearer token in the Authorization header. To obtain an API key, visit your organization settings or contact your Cheers account administrator.

Example Request
curl -X GET "https://app.cheers.tech/api/public/v1/organizations?organization_id=123" \
-H "Authorization: Bearer YOUR_API_KEY"

Rate Limits

Limits use a sliding 60-second window and are scoped by API key and endpoint. A request that passes the limiter consumes a slot even if later validation fails.

SurfaceLimitDetails
GET endpoints100 requests per 60 secondsPer API key and endpoint. Different GET endpoints have independent counters.
Single POST or DELETE /employee-links500 requests per 60 secondsShared per API key across single employee-link provisioning and termination requests.
Bulk POST or DELETE /employee-links10 batch requests per 60 secondsBulk POST accepts up to 1,000 items and at most 100 link writes per batch: each distinct agent_id with card_scope agent counts once, and each card_scope location item counts once. Bulk DELETE accepts up to 100 items. Items are processed with bounded concurrency of 10 and return per-item results. Bulk calls also consume one slot from the shared 500-request standard bucket.
PATCH /cards500 requests per 60 secondsPer API key.

A limited request returns 429 Too Many Requests with Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. Wait for Retry-After seconds, then retry the same request unchanged.

Common Parameters

Most endpoints support the following query parameters for filtering, pagination, and date-based queries.

ParameterTypeRequiredDescription
organization_idinteger
Optional
Filter by specific organization ID
parent_organization_idinteger
Optional
Get data for all child organizations
fromISO 8601 datetime
Optional
Entity activity/updated-time lower bound. Reporting endpoints instead filter observation dates (website scores: week_start); see Dataset and sync guide.
toISO 8601 datetime
Optional
Inclusive upper bound for the endpoint-specific date/activity filter.
created_fromISO 8601 datetime
Optional
Filter records created after this time
created_toISO 8601 datetime
Optional
Filter records created before this time
limitinteger
Optional
Maximum rows per page (default 100). Endpoint caps vary: 500 for GBP, Search, keywords and audit scores, 999 for Map Pack and snapshot exports, 1000 for AI visibility and other listed offset exports.
offsetinteger
Optional
Offset pagination only. Nonzero offsets are rejected by AI visibility and Map Pack; any explicit offset selects legacy reviews/taps mode.

Note: Either organization_id or parent_organization_id is required for initial scoped export requests; Map Pack accepts only organization_id. Reviews/taps cursor and checkpoint continuations must contain only that token.

Dataset and sync guide

Start with the dataset you need. A successful HTTP response or a returned row does not establish complete source coverage. All paths below are relative to /api/public/v1.

DatasetScope and upsert keyPaginationFreshness and limitations
Organizations
/organizations
Key organization and descendants; key: id. organization_type distinguishes ADMIN, BRAND, LOCATION, SERVICE_AREA and DEPARTMENT.Offset; max 1000. X-Total-Count.Current organization metadata, not evidence that each organization has a connected provider.
Cards
/cards
One organization or key hierarchy; key: id.Offset; max 1000. Stop on a short or empty page.Active cards only. Reconcile a full inventory periodically to detect cards that became inactive.
Links
/links
One organization or key hierarchy; key: id.Offset; max 1000. Stop on a short or empty page.Configured link metadata for joining interaction records.
Reviews
/reviews
One organization or key hierarchy; key: id. Use format=v2 for full fields.Snapshot cursor/checkpoint; max 999. Explicit offset selects legacy mode.Retains provider-removed reviews as not_showing=true. Exclude these only when computing visible-review counts, not when storing sync history.
Taps
/taps
One organization or key hierarchy; key: id.Snapshot cursor/checkpoint; max 999. Explicit offset selects legacy mode.Recorded tap events. Agent-scoped taps use the resolved destination organization.
Link interactions
/link_interactions
One organization or key hierarchy; key: id.Offset; max 1000. Stop on a short or empty page.Recorded interactions; an agent journey keeps the organization of its originating tap.
GBP performance
/gbp-performance
Non-ADMIN organizations; key: (organization_id, date). Metrics belong to the connected business profile.Offset; max 500. X-Total-Count.Daily org/date placeholders include unavailable rows. Missing metrics are null; optional bookings/messages may be absent even when core metrics are complete.
Search performance
/search-performance
Non-ADMIN organizations; key: (organization_id, date). GSC/GA4 facts belong to the organization with the connected property, commonly the brand.Offset; max 500. X-Total-Count.Property totals are not automatically attributed to individual locations. GSC and GA4 report independent status; retain available GA4 values when the combined row is partial.
Search keywords
/search-keywords
Connected property organization; key: (organization_id, date, query).Offset; max 500. X-Has-More. Windows ≤31 days.Retained daily top 500 queries per organization by impressions. The legacy coverage label ends in per_location but refers to organization_id, including BRAND property owners. Query totals need not equal property totals; missing queries do not mean zero searches.
Map Pack rankings
/map-pack-rankings
One location/service area at a time; key: result_id. Rows represent keyword/grid-point observations in completed runs.Observation cursor; max 999. Windows ≤31 days.Inspect run_data_status and grid-point counts for partial scans. Null business_rank means not found in observed results, not rank zero. Uncollected historical scans cannot be recreated by an export.
AI visibility
/ai-visibility
Location × date × prompt × platform by default; scope=brand or scope=all adds brand-wide prompts (null location_id). Key: (organization_id, date, ai_prompt_id, ai_platform_id).Observation cursor; max 1000. 503 with Retry-After on a timed-out query.Four or more runs are complete, one to three partial, zero unavailable. Most prompts run once per platform per day, so single daily rows are usually partial. Rank measures structured map/place position, separately from written-answer appearances. rank_samples is zero for no recorded ranks or null for an unknown legacy count; weight non-null rank averages by positive sample counts. Sentiment is not included in this public export.
Website audit scores
/website-optimization-scores
Audited organization; key: audit_run_id. Date filters select week_start.Offset; max 500. X-Has-More.One row per stored audit run. Blocked, failed and unfinished audits expose availability_reason instead of usable scores. An HTTP 200 challenge page can still block an audit.

Choose the right organization

Use parent_organization_id equal to the organization that owns your API key to include its hierarchy, where the endpoint supports it. Use organization_id to select one allowed organization; it does not imply that organization's descendants. Send one selector. First paginate /organizations to build your ID mapping. For Map Pack, select LOCATION and SERVICE_AREA rows and request each ID separately; parent_organization_id is not supported. For Search, request the brand/property organization instead of assuming each location has separate GA4 or GSC data.

Freshness, partial rows and backfills

Google reporting can arrive or change after the observation date. Cheers also uses a configurable stable-data cutoff: the default GBP and GSC collection cutoff is five days behind, followed by each organization's scheduled refresh. This is a collection policy, not a guarantee that Google always takes five days. GA4 is collected independently. Check source observation timestamps and source-specific statuses, not just the latest successful fetch or the presence of a daily placeholder.

  1. Choose explicit observation dates and complete every page for that scope/window.
  2. Re-fetch an overlapping window daily and upsert by the keys above. A 14-day overlap is a useful starting point; expand it when an older gap or correction is reported. Source retention and access still bound what can be recovered. Export GET requests read stored observations; they do not trigger a new Google fetch.
  3. Keep partial rows and available fields. Null means unavailable or unobserved; zero is an observed value. Preserve availability metadata and source status alongside metrics.
  4. Check expected organizations and source-day coverage after the export. A complete cursor chain proves you retrieved the requested stored rows, not that every source observation exists. Record counts must use the same scope, dates, source and deletion/active filters to reconcile.

Endpoints

GET/organizations

Retrieve organization details.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
Specific organization ID (one of organization_id or parent_organization_id required)
parent_organization_idinteger
Optional
Get all child organizations (one of organization_id or parent_organization_id required)
citystring
Optional
Exact city match, case-insensitive
statestring
Optional
Exact state name or code match, case-insensitive
is_activeboolean
Optional
Filter active or inactive locations

Response Fields

FieldTypeDescription
idintegerOrganization ID
namestringOrganization name
organization_typestringADMIN, BRAND, LOCATION, SERVICE_AREA, or DEPARTMENT; use to select the correct reporting scope
created_atdatetimeWhen the organization was created
updated_atdatetimeLast update timestamp
billing_statusstringBilling status (NOT PAID, PAID, EXEMPT)
plan_tierstringProduct tier (STARTER, GROWTH, PRO, ENTERPRISE)
subscription_tierstringLegacy billing mirror; use billing_status going forward
parent_organization_idintegerParent organization ID (null if root)
citystringLocation city
statestringLocation state or region
latitudenumberLocation latitude
longitudenumberLocation longitude
timezonestringIANA timezone
is_activebooleanWhether the location is active
Request
curl -X GET "https://app.cheers.tech/api/public/v1/organizations?organization_id=123" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"id": 123,
"name": "Acme Restaurant",
"organization_type": "LOCATION",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-06-20T14:45:00Z",
"billing_status": "PAID",
"plan_tier": "GROWTH",
"subscription_tier": "PAID",
"parent_organization_id": null
}
]
GET/organization-connections

Retrieve platform connections for organizations (Google, Yelp, Facebook, etc.).

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
Specific organization ID (one of organization_id or parent_organization_id required)
parent_organization_idinteger
Optional
Get connections for all child organizations (one of organization_id or parent_organization_id required)

Response Fields

FieldTypeDescription
organization_idintegerOrganization ID
google_place_idstringGoogle Places ID
google_account_idstringGoogle Business Profile account ID
google_location_idstringGoogle Business Profile location ID
yelp_business_idstringYelp business ID
tripadvisor_location_idstringTripadvisor location ID
facebook_page_idstringFacebook page ID
facebook_urlstringFacebook page URL
trustpilot_company_websitestringTrustpilot company identifier
bbb_profile_urlstringBetter Business Bureau profile URL
created_atdatetimeWhen the connection was created
Request
curl -X GET "https://app.cheers.tech/api/public/v1/organization-connections?organization_id=123" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"organization_id": 123,
"google_place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
"google_account_id": "accounts/123456789",
"google_location_id": "locations/987654321",
"yelp_business_id": "acme-restaurant-new-york",
"tripadvisor_location_id": null,
"facebook_page_id": "123456789012345",
"facebook_url": "https://facebook.com/acmerestaurant",
"trustpilot_company_website": null,
"bbb_profile_url": null,
"created_at": "2024-01-15T10:30:00Z"
}
]
GET/cards

Retrieve badge/card information for your organization.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
Specific organization ID (one of organization_id or parent_organization_id required)
parent_organization_idinteger
Optional
Get cards for all child organizations (one of organization_id or parent_organization_id required)

Response Fields

FieldTypeDescription
idstring (UUID)Unique card identifier
created_atdatetimeWhen the card was created
updated_atdatetimeLast update timestamp
cardholder_namestringName of the badge holder
employee_idstring (UUID)Employee represented by the card
organization_idintegerOrganization ID
titlestringBadge holder's title/position
photo_urlstringURL to badge holder's photo
encode_urlstringEncoded URL for the badge
linktree_enabledbooleanWhether linktree is enabled for this card
direct_link_idintegerExplicit direct review destination, when configured
badge_numberstringCustom badge identifier
Request
curl -X GET "https://app.cheers.tech/api/public/v1/cards?organization_id=123" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"created_at": "2024-03-01T09:00:00Z",
"updated_at": "2024-03-15T14:30:00Z",
"cardholder_name": "John Smith",
"organization_id": 123,
"title": "Server",
"photo_url": "https://storage.cheers.tech/photos/john-smith.jpg",
"encode_url": "https://app.cheers.tech/t/abc123",
"linktree_enabled": true,
"badge_number": "EMP-001"
}
]
PATCH/cards

Update a card's organization assignment.

Request Body

ParameterTypeRequiredDescription
cardIdstring (body)
Optional
Card UUID to update (one of cardId or badge_number required)
badge_numberstring (body)
Optional
Badge number for bulk update (one of cardId or badge_number required)
organization_idinteger (body)
Required
Target organization ID
Request
curl -X PATCH "https://app.cheers.tech/api/public/v1/cards" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"cardId": "550e8400-e29b-41d4-a716-446655440000", "organization_id": 456}'
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": 456,
"updated_at": "2026-10-02T12:00:00.000Z"
}
GET/taps

Retrieve tap events (when a customer taps a badge). Agent-scoped taps are attributed to the resolved destination organization.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
Specific organization ID (one of organization_id or parent_organization_id required)
parent_organization_idinteger
Optional
Get taps for all child organizations (one of organization_id or parent_organization_id required)

Response Fields

FieldTypeDescription
idintegerTap ID
created_atdatetimeWhen the tap occurred
updated_atdatetimeLast update timestamp
card_idstring (UUID)Associated card ID
organization_idintegerOrganization attributed to the tap. For an agent-scoped card, this is the validated destination organization; otherwise it is the card organization.
sourcestringRecorded source of the visit
usedbooleanWhether the tap resulted in a completed action
Request
curl -X GET "https://app.cheers.tech/api/public/v1/taps?organization_id=123&from=2024-01-01T00:00:00Z" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"id": 12345,
"created_at": "2024-06-15T18:30:00Z",
"updated_at": "2024-06-15T18:30:00Z",
"card_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": 123,
"source": "badge",
"used": true
}
]
GET/reviews

Retrieve customer reviews from all connected platforms. Agent attribution is retained when Cheers can match the review to a recorded journey.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
Specific organization ID (one of organization_id or parent_organization_id required)
parent_organization_idinteger
Optional
Get reviews for all child organizations (one of organization_id or parent_organization_id required)
formatstring
Optional
Use "v2" or "new" for full response fields

Response Fields

FieldTypeDescription
idintegerReview ID
created_atdatetimeWhen the review was received
updated_atdatetimeLast update timestamp
ratingintegerRating value (1-5)
card_idstringAssociated card ID (if attributed)
review_textstringFull review text
organization_idintegerOrganization ID
sourcestringPlatform source (GOOGLE, YELP, FACEBOOK, etc.)
reviewer_namestringReviewer's display name
reviewer_photo_urlstringReviewer's profile photo
owner_responsestringBusiness owner's response
response_timestampdatetimeWhen the response was posted
review_urlstringDirect link to the review
internalbooleanWhether this is an internal Cheers review
not_showingbooleanWhether the review is retained in API history but no longer showing on the source platform
not_showing_atdatetimeWhen Cheers detected the review was no longer showing on the source platform; null when not_showing is false
Request
curl -X GET "https://app.cheers.tech/api/public/v1/reviews?organization_id=123&format=v2" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"id": 5678,
"created_at": "2024-06-10T12:00:00Z",
"updated_at": "2024-06-10T12:00:00Z",
"rating": 5,
"card_id": "550e8400-e29b-41d4-a716-446655440000",
"review_text": "Amazing service! John was incredibly helpful.",
"organization_id": 123,
"source": "GOOGLE",
"reviewer_name": "Jane D.",
"reviewer_photo_url": "https://lh3.googleusercontent.com/...",
"owner_response": "Thank you for the kind words!",
"response_timestamp": "2024-06-11T09:00:00Z",
"review_url": "https://search.google.com/local/reviews?...",
"internal": false,
"not_showing": false,
"not_showing_at": null
}
]
GET/gbp-performance

Retrieve daily Google Business Profile Search, Maps, and customer-action metrics by location.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
Specific location (one of organization_id or parent_organization_id required)
parent_organization_idinteger
Optional
Root organization and all permitted descendants
fromISO date or datetime
Optional
First calendar date; defaults to the previous 30 complete UTC dates
toISO date or datetime
Optional
Last calendar date
limitinteger
Optional
Maximum rows, up to 500
offsetinteger
Optional
Rows to skip

Response Fields

FieldTypeDescription
organization_idintegerCheers location organization ID
datedateMetric calendar date
data_statuscomplete | partial | unavailableComplete when all core metrics are present; partial when an observation has a missing core metric; unavailable when no observation exists
availability_reasonstring | nullWhy a row is not complete: not_yet_reported_by_google (Google reports each metric several days late, and every missing metric falls after Google's latest reported day), missing_metric_observation, missing_daily_observation, or google_not_connected
search_viewsinteger | nullCombined desktop and mobile Search impressions
maps_viewsinteger | nullCombined desktop and mobile Maps impressions
website_clicksinteger | nullWebsite actions
phone_callsinteger | nullCall actions
direction_requestsinteger | nullDirection actions
total_actionsinteger | nullWebsite clicks + phone calls + direction requests
bookingsinteger | nullBookings, reported separately from total_actions; null when Google has not reported them
messages_receivedinteger | nullProfile conversations; null when Google has not reported them
last_updated_atdatetime | nullFreshness timestamp for the observation
Request
curl -X GET "https://app.cheers.tech/api/public/v1/gbp-performance?parent_organization_id=123&from=2026-08-01&to=2026-08-07&limit=500" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"organization_id": 456,
"date": "2026-08-01",
"data_status": "complete",
"search_views": 320,
"maps_views": 184,
"website_clicks": 12,
"phone_calls": 8,
"direction_requests": 5,
"total_actions": 25,
"bookings": 2,
"last_updated_at": "2026-08-02T12:00:00.000Z"
}
]
GET/search-performance

Retrieve daily Google Search Console, Google Analytics, referral, and Cheers Search Visibility metrics by organization.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
Specific non-ADMIN organization (exactly one scope selector is required)
parent_organization_idinteger
Optional
Root organization and all permitted non-ADMIN descendants
fromISO date or datetime
Optional
First calendar date; defaults to the previous 30 complete UTC dates
toISO date or datetime
Optional
Last calendar date
limitinteger
Optional
Maximum organization/day rows, up to 500
offsetinteger
Optional
Rows to skip

Response Fields

FieldTypeDescription
organization_idintegerCheers organization ID; may identify a BRAND with the connected property
datedateMetric calendar date
data_statuscomplete | partial | unavailableCombined source availability for the organization/day
search_impressions, search_clicksinteger | nullAuthoritative Search Console property totals
search_ctrnumber | nullSearch click-through rate as a 0–1 ratio
average_search_positionnumber | nullAverage Search Console position
sessions and channel fieldsinteger | nullGA4 total, organic, direct, referral, social, and paid sessions
search_visibility_scorenumber | nullStored Cheers Search Visibility score
source status/freshnessstring | datetime | nullPer-source maintained ingest receipts, fetch status, and freshness metadata
Request
curl -X GET "https://app.cheers.tech/api/public/v1/search-performance?parent_organization_id=123&from=2026-08-01&to=2026-08-07&limit=500" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"organization_id": 456,
"date": "2026-08-01",
"data_status": "complete",
"search_impressions": 950,
"search_clicks": 74,
"search_ctr": 0.0779,
"average_search_position": 6.4,
"sessions": 410,
"organic_sessions": 220,
"referral_sessions": 31,
"search_visibility_score": 72,
"last_updated_at": "2026-08-04T12:00:00.000Z"
}
]
GET/search-keywords

Retrieve daily Google Search Console query metrics by organization.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
Specific non-ADMIN organization (exactly one scope selector is required)
parent_organization_idinteger
Optional
Root organization and all permitted non-ADMIN descendants
fromISO date or datetime
Optional
First calendar date; maximum 31-day window
toISO date or datetime
Optional
Last calendar date
limitinteger
Optional
Maximum rows, up to 500
offsetinteger
Optional
Rows to skip

Response Fields

FieldTypeDescription
organization_idintegerCheers organization ID; may identify a BRAND with the connected property
datedateMetric calendar date
querystringGoogle Search query
impressions, clicksintegerDaily query impressions and clicks
search_ctrnumber | nullDaily query click-through rate as a 0–1 ratio
average_search_positionnumber | nullDaily query average position
coveragestringLegacy label daily_top_500_queries_by_impressions_per_location; the bound applies per organization/day, including BRAND property owners
last_updated_atdatetimeFreshness timestamp
Request
curl -X GET "https://app.cheers.tech/api/public/v1/search-keywords?parent_organization_id=123&from=2026-08-01&to=2026-08-07&limit=500" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"organization_id": 456,
"date": "2026-08-01",
"query": "best electricity provider",
"impressions": 85,
"clicks": 7,
"search_ctr": 0.0824,
"average_search_position": 5.2,
"coverage": "daily_top_500_queries_by_impressions_per_location"
}
]
GET/website-optimization-scores

Retrieve Website Optimization audit state and versioned site scores.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
Specific organization in the API key hierarchy
parent_organization_idinteger
Optional
Root organization and all permitted descendants
fromISO date or datetime
Optional
First audit week_start date
toISO date or datetime
Optional
Last audit week_start date
limitinteger
Optional
Maximum rows, up to 500
offsetinteger
Optional
Rows to skip

Response Fields

FieldTypeDescription
audit_run_idUUIDStable audit run identifier
organization_idintegerCheers organization ID
week_startdateAudit week
data_statuscomplete | unavailableWhether comparable site scores exist
availability_reasonstring | nullTyped unavailable reason
audit_status, audit_phasestringAudit lifecycle state
score fieldsnumber | nullOverall, schema, AI readiness, content, performance, and crawlability scores
score_model_versioninteger | nullScore formula version required for comparison
Request
curl -X GET "https://app.cheers.tech/api/public/v1/website-optimization-scores?parent_organization_id=123&from=2026-07-01&to=2026-08-31" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"audit_run_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": 456,
"week_start": "2026-08-17",
"data_status": "complete",
"overall_score": 82,
"schema_score": 70,
"ai_readiness_score": 88,
"content_score": 80,
"performance_score": 76,
"crawlability_score": 91,
"score_model_version": 15
}
]
GET/map-pack-rankings

Retrieve every grid-point rank observation from completed Google Local Finder runs.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Required
One non-ADMIN location in the API key hierarchy
fromISO date or datetime
Optional
First UTC capture date; maximum 31-day window
toISO date or datetime
Optional
Last UTC capture date
limitinteger
Optional
Maximum grid rows, up to 999
cursorstring
Optional
Opaque X-Next-Cursor value from the previous page

Response Fields

FieldTypeDescription
organization_idintegerCheers location organization ID
tracked_keyword_id, keywordUUID | stringTracked search term identity
run_idUUIDGroup key for one completed grid run
grid_generationintegerVersioned grid identity
grid_row, grid_colintegerZero-based grid placement
latitude, longitudenumberExact query point coordinates
run_data_statuscomplete | partial | unknownRun-level grid completeness
grid-point countsinteger | nullExpected, succeeded, failed, and invalid point counts
business_rankinteger | nullNumerical rank within the observed results
rank_statusranked | not_rankedExplicit null-rank meaning
ranking_methodorganic | legacy | nullorganic ranks leave out sponsored listings; legacy rows (before the change) could count up to three ads ahead of the business, so don't compare ranks across the two. null when the row carries no method marker
Request
curl -X GET "https://app.cheers.tech/api/public/v1/map-pack-rankings?organization_id=456&from=2026-08-01&to=2026-08-07&limit=500" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"organization_id": 456,
"keyword": "electric company",
"run_id": "0787d09e-89a3-4dab-ac2a-cb7927d30aa2",
"grid_generation": 3,
"grid_row": 0,
"grid_col": 0,
"latitude": 29.7604,
"longitude": -95.3698,
"business_rank": 7,
"rank_status": "ranked",
"ranking_method": "organic",
"run_data_status": "complete",
"grid_points_expected": 25,
"grid_points_succeeded": 25,
"grid_points_failed": 0,
"grid_points_invalid": 0
}
]
GET/ai-visibility

Retrieve daily brand appearance, rank, and citation metrics by location, prompt, and AI platform, and optionally for brand-wide prompts that are not tied to a location.

Query Parameters

ParameterTypeRequiredDescription
organization_idinteger
Optional
One organization only, without its descendants. Location rows belong to the location organization that owns the tracked location, so a brand or root organization usually has no location rows of its own; use parent_organization_id for its locations, or scope=brand for its brand-wide prompts. One of organization_id or parent_organization_id is required.
parent_organization_idinteger
Optional
Your API key's root organization. Returns rows for the root and every permitted descendant.
scopelocation | brand | all
Optional
location (default) returns location rows only, as before. brand returns brand-wide prompts that have no tracked locations. all returns both; location prompts are never repeated at the brand level.
fromISO date or datetime
Optional
First calendar date
toISO date or datetime
Optional
Last calendar date
limitinteger
Optional
Maximum rows, up to 1000
cursorstring
Optional
Opaque X-Next-Cursor value from the previous page

Response Fields

FieldTypeDescription
brand_idinteger | nullCheers organization ID for the tracked brand
brand_namestring | nullTracked brand name
location_idinteger | nullCheers location organization ID; null on brand rows
location_namestring | nullLocation name; null on brand rows
organization_idintegerOrganization that owns the row: the location on location rows, the brand on brand rows. (organization_id, date, ai_prompt_id, ai_platform_id) is unique across both row types.
scopelocation | brandlocation rows measure a prompt tracked at one location. brand rows measure a brand-wide prompt with no tracked locations, such as a question about the brand itself.
datedateMetric calendar date
ai_prompt_idstringTracked prompt ID
ai_promptstring | nullTracked prompt text
ai_platform_idstringAI platform/provider UUID (use ai_platform for the display name)
ai_platformstring | nullAI platform/provider name
data_statuscomplete | partial | unavailableEvidence in this one row: complete at 4 or more valid runs, partial at 1 to 3, unavailable at 0. Most prompts run once per platform per day, so a single daily row is usually partial even when collection worked.
runsintegerValid observations included in the row
minimum_complete_runsintegerQuality threshold for complete status; not the prompt schedule
appearancesinteger | nullObserved appearances; null when no valid observations exist
appearance_rate_pctnumber | nullAppearance rate reported as a percentage
avg_rank_when_presentnumber | nullAverage business position in structured map/place listings, not order in the written AI answer. Null without valid observations, a positive rank_samples count, and a stored average.
rank_samplesinteger | nullObservations with a recorded map/place rank used for the average. Zero means no recorded ranks; null means the sample count is unknown for a legacy aggregate.
citationsinteger | nullObserved citations; null when no valid observations exist
citation_rate_pctnumber | nullCitation rate reported as a percentage
last_updated_atdatetimeFreshness timestamp
Request
curl -X GET "https://app.cheers.tech/api/public/v1/ai-visibility?parent_organization_id=123&scope=all&from=2026-08-01&to=2026-08-07&limit=1000" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
[
{
"brand_id": 123,
"brand_name": "Example Energy",
"location_id": 456,
"location_name": "Houston",
"organization_id": 456,
"scope": "location",
"date": "2026-08-01",
"ai_prompt_id": "9018cc4f-5170-42b3-9bfd-493d91bf2f81",
"ai_prompt": "best electricity provider in Houston",
"ai_platform_id": "2c53a16e-013b-4c63-8afc-805f1fa4d9ce",
"ai_platform": "ChatGPT",
"data_status": "complete",
"runs": 20,
"minimum_complete_runs": 4,
"appearances": 12,
"appearance_rate_pct": 60,
"avg_rank_when_present": null,
"rank_samples": 0,
"citations": 7,
"citation_rate_pct": 35,
"last_updated_at": "2026-08-02T12:00:00.000Z"
},
{
"brand_id": 123,
"brand_name": "Example Energy",
"location_id": null,
"location_name": null,
"organization_id": 123,
"scope": "brand",
"date": "2026-08-01",
"ai_prompt_id": "5b0d3c1e-8f7a-4f45-9a51-2f3f8c0f6d11",
"ai_prompt": "Is Example Energy legit?",
"ai_platform_id": "2c53a16e-013b-4c63-8afc-805f1fa4d9ce",
"ai_platform": "ChatGPT",
"data_status": "partial",
"runs": 1,
"minimum_complete_runs": 4,
"appearances": 1,
"appearance_rate_pct": 100,
"avg_rank_when_present": null,
"rank_samples": 0,
"citations": 1,
"citation_rate_pct": 100,
"last_updated_at": "2026-08-02T09:10:00.000Z"
}
]

Error Handling

All endpoints return consistent error responses with appropriate HTTP status codes.

Status CodeDescription
207Multi-Status - Batch completed with one or more failed items
400Bad Request - Missing or invalid parameters
401Unauthorized - Invalid or missing API key
403Forbidden - No access to requested resource
404Not Found - Resource does not exist
429Too Many Requests - Rate limit exceeded
500Internal Server Error
503Service Unavailable - Rate limiter or another required service is unavailable, or a query timed out; retry after Retry-After seconds when present
Error Response Format
{
"error": "Error message describing the issue"
}

Pagination

Pagination differs by endpoint. Always send your Bearer key, URL-encode tokens, and retain the same scope and date filters unless using a token-only snapshot continuation. Respect HTTP 429 Retry-After; do not mark a failed or incomplete export as complete.

Offset exports

Advance offset by the requested page limit (or X-Limit when provided). For organizations, GBP and Search performance, stop when the next offset reaches X-Total-Count. For search keywords and website scores, follow X-Has-More. Cards, links and link interactions have no total-count header: continue until a short or empty page. Stable ordering is not a snapshot under concurrent changes; use overlapping syncs and periodic reconciliation.

Offset continuation
GET /search-performance?parent_organization_id=123&from=2026-09-01&to=2026-09-07&limit=100&offset=0
GET /search-performance?parent_organization_id=123&from=2026-09-01&to=2026-09-07&limit=100&offset=100

AI visibility and Map Pack cursors

Keep the original organization, dates and limit on every request; add X-Next-Cursor as the cursor parameter. Map Pack uses X-Has-More and X-Next-Cursor. AI visibility ends when no X-Next-Cursor is returned; an exact-size final page may require one extra empty request. Do not reuse a cursor across locations or date windows. These are observation cursors, not saved incremental checkpoints.

Observation cursor continuation
GET /map-pack-rankings?organization_id=456&from=2026-09-01&to=2026-09-07&limit=999
GET /map-pack-rankings?organization_id=456&from=2026-09-01&to=2026-09-07&limit=999&cursor=URL_ENCODED_TOKEN
GET /ai-visibility?parent_organization_id=123&from=2026-09-01&to=2026-09-07&limit=1000
GET /ai-visibility?parent_organization_id=123&from=2026-09-01&to=2026-09-07&limit=1000&cursor=URL_ENCODED_TOKEN

Reviews and taps snapshots

For taps and reviews, omit offset to use immutable cursor pagination. Follow the X-Next-Cursor header until X-Has-More is false, then save the final X-Checkpoint for the next incremental run.

Pagination Example
# Start an immutable export (1-999 rows per page)
GET /reviews?parent_organization_id=123&format=v2&limit=500
# Continue the same session; send no other query parameters
GET /reviews?cursor=VALUE_FROM_X_NEXT_CURSOR
# Start the next incremental run after the prior final page commits
GET /reviews?checkpoint=VALUE_FROM_X_CHECKPOINT

Cursor sessions expire after six hours; metadata-only checkpoints expire after seven days. Upsert by record ID and only advance a checkpoint after every page succeeds. Explicit offset is legacy compatibility mode.

Filtering by Date

Daily reporting endpoints use inclusive observation dates (YYYY-MM-DD); website scores filter audit week_start. Their last_updated_at field is metadata, not an updated-since filter. Entity exports use ISO 8601 timestamps for activity/updated and created filters. Reviews include late ingestion and deletion-detection activity, so do not re-filter returned reviews solely by their visible created_at or updated_at values:

Date Filtering Examples
# Reviews updated in the last 7 days
GET /reviews?organization_id=123&from=2024-06-08T00:00:00Z
# Reviews created in January 2024
GET /reviews?organization_id=123&created_from=2024-01-01T00:00:00Z&created_to=2024-01-31T23:59:59Z

Need Help?

For API support, contact us at info@cheers.tech