Developer HubVersion 3.51 Updated August 22, 2026

v3.24 changelog (beta feature): Local Growth is now location-first. Local Growth is scoped to one managed Google business at a time, chosen in a single persistent Working on selector above the tabs. That choice is written into the URL as ?loc=<locationId> and remembered between visits, so every Local Growth deep link now carries the business it is about (for example /admin/local-growth?tab=reviews&panel=widgets&loc=<locationId>). All nine per-tab location pickers were removed — Profile, Reviews, Requests (Compose / Sent / Call Tracking), Content (Compose / Media), Performance and Optimization all inherit the selected business. Fleet-wide roll-up is now an explicit in-tab control (Compare all locations) on Performance, Optimization, Activity and Requests → Sent only; the Working-on selector never holds "all locations". Content → Compose now targets the selected business by default and offers Also publish to other locations for deliberate multi-location posting — locationIds in POST /api/admin/local-growth/posts is unchanged, but the UI no longer pre-selects every managed location. GET /api/admin/local-growth/activity accepts a new optional locationId parameter (entries with no recorded location, such as a fleet sync, remain visible in every location view). No breaking API changes. The local-growth entitlement is still in closed beta.

v3.23 changelog (beta feature): Local Growth Phase D cleanup. (1) Review Widgets gained layout: "carousel", maxReviews (1–5, clamped to Google's 5-review ceiling) and showCta. When Google supplies a Leave-a-Review URL for the location it is returned as place.newReviewUrl and the widget renders a "Leave a review" button — the URL is taken from Google's own metadata.newReviewUrl and is never constructed, so it is simply absent when Google has not provided one. (2) Native site section — the site builder now has a Google Reviews section that points at a saved Review Widget (one source of truth; styling still lives on the widget). No iframe needed on KOINETIC sites; the copyable embed snippet remains for external sites. (3) Logo & cover uploads (POST /api/admin/local-growth/photos) no longer fail as a whole when Google rejects an image: the KOINETIC copy is always stored, the response returns googlePushed, googleError and a per-category photoSyncState (status, at, sourceUrl, error, detail), and the panel offers a Retry publish to Google action. A rejection also emits the profile.photo_sync_failed automation event. (4) KOINETIC Local Score re-weighted to profile 35 / posts 15 / reviews 25 / responses 15 / photos 10, and a location with zero reviews now scores 0 of 15 on responses (previously full marks) with a critical "earn your first review" recommendation. GET /api/admin/local-growth/optimization now also returns pillarWeights. The weights and formula variables are platform policy — set by Abacus/KOINETIC platform administrators only, not per workspace. (5) New automation triggers gbp.no_post_reminder and gbp.weekly_digest, plus a milestone and reviewTotal field on review.submitted for review-milestone automations (detected the moment the review lands — no scheduled job). Configure thresholds, the quiet-listing window (default 14 days) and the weekly digest day/hour/timezone via GET|PUT /api/admin/local-growth/reminders or Local Growth → Overview → Reminders & digest. Four ready-made recipes were added to the Automations Recipes panel; the existing universal negative-review recipe was kept alongside the new Google-specific one. The local-growth entitlement is still in closed beta.

v3.22 changelog (beta feature): Local Growth Phase D complete — Review Widgets, Optimization corrections, and automation recipes. (1) Review Widgets (Reviews → Widgets, ?tab=reviews&panel=widgets): GET|POST|PATCH|DELETE /api/admin/local-growth/review-widgets manages per-location embeddable review widgets (name, minRating where 0 = show all, theme light/dark, layout grid/list, accentColor, showHeader, isActive). Each widget has a public publicId and two public, unauthenticated embed surfaces: GET /embed/reviews/{publicId} (an noindex HTML page you drop into an <iframe>) and GET /api/public/local-growth/review-widget?id={publicId} (JSON, CORS *, for script embeds). Reviews are read live from the Places API (New) at request time — never from stored review rows — hard-capped at 5, always shown with author attribution, and if a star-rating filter hides reviews the widget discloses it. Needs the same Places API (New) key from Integrations → Google Business Profile. (2) Optimization → Website check now compares the full NAP (business Name, Address, Phone) plus web address against your live site, and adds a Search enhancements section reporting whether your site has structured-data (schema) markup and an FAQ section. (3) Automations: three ready-made Local Growth recipes were added — a reply reminder for new 3–4★ Google reviews, a 5★ showcase heads-up, and a "ask for a Google review a week after purchase" request — installable from the Automations Recipes panel and running on the existing automations engine. The local-growth entitlement is still in closed beta.

v3.21 changelog (beta feature): Local Growth — Optimization tab (?tab=optimization, subpanels &panel=score|competitors|consistency). New endpoint GET /api/admin/local-growth/optimization?locationId=&include=consistency,competitors returns {locations, scores, pillarWeights, consistency?, competitors?}. Each score is a KOINETIC Local Score (0-100 plus a letter grade) built from five weighted pillars — profile completeness (35), post recency & cadence (20), review volume & velocity (20), review response rate (15) and photo coverage from your own uploaded gallery (10) — with ranked recommendations that deep-link to the panel that fixes each one. The include=competitors extra compares the location against nearby businesses of the same category (about 8 km) using the Places API (New) and reports only fields Google returns as real totals: star rating, review count, category/types and business status. Photo counts are deliberately not reported — the Places photo array is a capped sample (max 10), not a business's photo total. The include=consistency extra fetches the location's own website once and reports whether the business name, phone number and web address match the listing. Both extras are opt-in because they make outbound calls. Competitor comparison requires a Places API (New) key, saved (encrypted) in the global Integrations → Google Business Profile credential modal; Places API (New) must be enabled on the same Google Cloud project and is billed separately from the Business Profile APIs. All nine Local Growth tabs are now live. The local-growth entitlement is still in closed beta.

v3.20 changelog (beta feature): Local Growth — Content & Performance tabs. Content (?tab=content): POST|GET|DELETE /api/admin/local-growth/posts (compose, list, delete Google posts — topic types STANDARD/EVENT/OFFER; CTA mapping BOOK/ORDER/SHOP/LEARN_MORE/SIGN_UP/CALL; Google-native scheduledTime for scheduling; multi-location fan-out with per-location status; actions: action=draft|publish|schedule); PATCH /api/admin/local-growth/posts (promote draft to publish or schedule); POST /api/admin/local-growth/posts/ai-assist (LLM-powered copy improvement); POST|GET|DELETE /api/admin/local-growth/media (gallery photo upload/list/delete — 10 categories, multipart upload ≤10 MB, 30-day cloud cleanup). Post reconciliation (dunning sweep job #3) pulls Google state for unsettled posts and retries only confirmed failures, idempotently. Performance (?tab=performance): GET /api/admin/local-growth/performance?locationId=&days=30 returns 7 daily metrics (CALL_CLICKS, WEBSITE_CLICKS, BUSINESS_DIRECTION_REQUESTS, BUSINESS_IMPRESSIONS_DESKTOP_MAPS/MOBILE_MAPS/DESKTOP_SEARCH/MOBILE_SEARCH), period-over-period comparison (delta + percent), and monthly search keywords (top 100, paginated from Google). Metrics sync runs in the dunning sweep (job #5). New schema models: GbpPost, GbpPostLocation, GbpMediaItem, GbpMetric, GbpKeyword. The local-growth entitlement is still in closed beta.

v3.19 changelog (beta feature): Local Growth — provider-agnostic messaging, generalized review-request rules, batch campaigns and configurable reminders. SMS/WhatsApp and call tracking are no longer Twilio-specific: they resolve whichever messaging provider is enabled through KOINETIC Integrations (Twilio, Telnyx, MessageBird, Vonage or Plivo — Managed by KOINETIC or the tenant's own BYOK credential). New canonical telephony webhooks GET|POST /api/integrations/telephony/voice/{locationId} and POST /api/integrations/telephony/status/{locationId} accept JSON or form-encoded payloads and emit the right call-control dialect for the connected provider; the old /api/integrations/twilio/... paths still work as delegates. GET /api/admin/local-growth/call-tracking now returns {connected, provider, providerLabel, mode, webhooks}. GET|POST|PATCH|DELETE|PUT /api/admin/local-growth/requests/settings became a multi-rule surface: create, edit, pause or delete any number of review-request rules on job.completed, appointment.completed, order.completed, order.delivered, order.shipped, order.paid, form.submitted or contact.created, each with its own wait, channel, location and message (rules are ordinary automations); PUT saves the reminder policy (maxReminders 0-5, default 2; reminderIntervalDays 1-30, default 3). New POST /api/public/events (authenticated with x-api-key) lets an external booking, field-service or POS system fire job.completed, appointment.completed or order.completed into those rules. New GET /api/admin/local-growth/requests/audience?source=contacts|customers&q= returns reachable recipients, and POST /api/admin/local-growth/requests now accepts a recipients[] array (max 500) to send one campaign to a whole list, responding {batch:true, sent, failed, errors}. The local-growth entitlement is still in closed beta.

v3.18 changelog (beta feature): Local Growth / Google Business Profile — Requests & Call Tracking. New endpoints: GET|POST|PATCH /api/admin/local-growth/requests (list review requests with per-stage stats and channel availability / create+send a request / mark a request converted or toggle its reminders); GET|PUT /api/admin/local-growth/requests/settings (report and toggle the order-delivered→review-request automation); GET|PUT /api/admin/local-growth/photos and POST (manage the location's logo & cover photo — multipart upload or JSON sourceUrl, pushed to Google's v4 media endpoint then mirrored locally); GET|PUT /api/admin/local-growth/call-tracking (per-location call-tracking config, recent call log, Twilio-connected flag and the webhook URLs to paste into Twilio). Public tracking/telephony routes (no auth): GET /rl/{code} (short-link click → 302 to the Google review form), GET /api/rl/{code}/o (email open pixel), GET|POST /api/integrations/twilio/voice/{locationId} (TwiML call forwarding), POST /api/integrations/twilio/status/{locationId} (Twilio status callback → call logging, missed-call text-back, review-after-call). Review requests send over email always (QR + short-link included); SMS/WhatsApp require a connected Twilio (BYOK) integration. Reminders (max 2, 3 days apart) run on the existing internal sweep. The local-growth entitlement is still in closed beta.

v3.17 changelog (beta feature): Local Growth / Google Business Profile — Profile completion endpoints. PATCH /api/admin/local-growth/profile now accepts specialHours and a categories block (primaryCategory + additionalCategories, each {name, displayName} where name is Google's categories/gcid:… resource name). New endpoints: GET /api/admin/local-growth/categories (category search, or a single category with its serviceTypes); GET|PATCH /api/admin/local-growth/attributes (available attribute metadata for the location's category plus current values — discovery uses the Business Information attributes metadata endpoint; PATCH writes with an attributeMask and mirrors URL-type attributes into socialLinks); GET|POST|PATCH|DELETE /api/admin/local-growth/place-actions (Place Action links and available action types via the dedicated Google Place Actions API — links returned with providerType: "PROVIDER" are aggregator-managed and read-only); GET|PATCH /api/admin/local-growth/services (serviceTypes for the category plus free-form serviceItems). All writes push to Google first and mirror locally on success. Endpoints require the local-growth entitlement, which is still in closed beta.

v3.16 changelog: Template buyer-affiliate program (70% floor) + single-source Template Buyer tier. (1) When a clone-mode listing goes ACTIVE, a "Template Affiliates — [name]" program is auto-created in the seller's affiliate engine with commission ≥ 70% (raise-only; PUT /api/admin/affiliates/programs enforces the floor and type-locks marketplace programs; DELETE is blocked for them). Every template buyer is auto-enrolled at purchase as an approved partner with a minted referral code (Stripe webhook, best-effort post-ledger). (2) POST /api/public/marketplace/{id}/checkout accepts an optional ref (≤64 chars) which is carried in transaction metadata; the webhook records an AffiliateConversion in the seller's program for the referring buyer. GET /api/public/marketplace/{id} now returns affiliateCommissionPercent. (3) GET /api/admin/marketplace now returns buyerPromo (referral URL, commission %, opt-in surface toggles) and a new PATCH /api/admin/marketplace saves {ribbonEnabled, badgeEnabled} (both default OFF; storefront runtime config exposes buyerPromo and renders a header ribbon / floating badge when enabled). (4) The Template Buyer tier is now managed exclusively in /admin/pricing: the marketplace POST no longer accepts buyerTier; PUT /api/admin/pricing forces isActive: true for template tiers and accepts showOnPricingPage + freeHostingMonths (0/3/6/12); DELETE is blocked for tiers linked to a listing. Platform 5% fee and the creator's 0–30% resale royalty (resellers always keep ≥70%) are separate from the buyer-affiliate payout.

v3.15 changelog: Lossless template switching + draft preview slot + directory add-on subpath. (1) PUT /api/admin/templates now merges the tenant's existing section content into the new template (losslessSwitchMerge) — switching templates never wipes customized sections. (2) New GET/POST /api/admin/templates/draft — one draft template slot per site (POST actions create / publish / discard); GET /api/admin/templates/sections?draft=1 and PUT with draft: true read/write the draft config; a shareable token-gated preview renders at /preview/<token>. Stored entirely in Settings — no schema change. (3) POST /api/admin/verticals no longer hard-blocks non-directory sites: the Directory Listings add-on unlocks the first vertical on a brand/agency site (runs under its own subpath with an additive nav item; extra verticals still require Multi-Vertical); GET response gains a directoryAddon flag.

v3.14 changelog: Template taxonomy rearranged: templates now use a three-level hierarchy (Type → Category → Vertical) replacing the flat category model. Ten categories across two types (directory / website) with starter verticals per category. GET /api/admin/templates response includes vertical field. Internal provisioning updated — no public API breaking changes.

v3.13 changelog: Template Marketplace ownership model corrected: a template buyer becomes the selling agency's client (a client sub-account under the agency, entitled via the agency's Template Buyer tier with its included free-hosting months) — never a KOINETIC platform subscriber. The buyer's workspace contains only the cloned site (no blank starter app). Payment attribution: the purchase transaction is recorded against the selling agency (the money receiver), so template sales appear in the agency's revenue dashboard and transaction list; GET /api/onboarding/template-status still returns the BUYER's new workspace id for the post-checkout session switch. Webhook provisioning is now outcome-idempotent — a purchase interrupted mid-provision self-heals on the next webhook retry.

v3.12 changelog: Template Marketplace buy-flow hardening. A template purchase now always provisions a brand-new cloned workspace for the buyer, even if they already own another workspace under the same login — previously an existing owner could pay the selling agency and have their old workspace merely reactivated (receiving nothing for their payment). The checkout.session.completed webhook now forces new-workspace creation for template purchases. Because the charge is a Connect direct charge (provisioned webhook-only), the /onboarding holding page now polls the new GET /api/onboarding/template-status?txn=<id> (auth; verifies the transaction belongs to the caller) and, once the workspace exists, switches the buyer's session into it (POST /api/admin/switch-tenant) before landing them in /admin — so buyers always land in the site they just bought, not their previous one.

v3.11 changelog: Live Template Marketplace — buying a template now charges the SELLING AGENCY, not KOINETIC. New POST /api/public/marketplace/{id}/checkout (auth required) resolves the clone-mode listing → seller workspace and opens a Stripe Connect direct charge on the seller's connected account at the agency's asking price (agency = merchant of record; KOINETIC takes an application_fee, default 5%). If the seller hasn't configured/finished Stripe it returns 503 (STRIPE_NOT_CONFIGURED / SELLER_PAYMENTS_NOT_READY) — it never falls back to KOINETIC's own billing. Buyer path: koinetic.com/select-plan?templateId=<id> shows the selling agency's brand card when signed out, then routes straight to the agency checkout after login (the KOINETIC plan grid is skipped for template links). On payment, the checkout.session.completed webhook provisions the buyer's cloned workspace (hosted under the selling agency) and lands them in /admin. POST /api/onboarding/checkout reverted to KOINETIC-plan-only (no template bypass).

KOINETIC is the private operating layer behind custom digital properties. This document is the complete reference for building a front-end against the KOINETIC public API. It covers every public endpoint, the bootstrap config, data models, app resolution, the template system, storefront rendering, rate limits, webhook events, and example payloads — so you can build the exact front end a property needs while KOINETIC handles the structured backend, data, permissions, and integrations behind it. No source-code access required.

1. Architecture Overview

KOINETIC is a multi-tenant operating layer — a structured CMS + directory backend that powers many independent properties from one private control plane. The hierarchy:

PlatformPlan
 └── Builder (org / customer)
      └── App (one app per builder)
           ├── Site(s)   → Domain(s)     ← how requests are routed
           ├── Settings   (theme, SEO, social)
           ├── Categories → Listings
           ├── Pages      (CMS)
           ├── Articles   (Blog)
           ├── PricingTiers → TierFeatures
           ├── Forms → FormSubmissions
           ├── ContentTypes → ContentFields → ContentRecords
           ├── Reviews
           ├── Notifications (banners)
           ├── LegalSnippets
           ├── NavigationMenus
           ├── Webhooks
           ├── Media
           ├── EmailTemplates
           ├── Claims
           ├── Contacts
           ├── Blueprint? → Vertical data model (field schema, sub-directories, monetization)
           └── Template?  → Sections, Theme, PageLayouts

Key Concepts:

  • Each Builder has exactly one App.
  • Each App has one or more Sites, each with one or more Domains.
  • The incoming request's Host header determines which App's data is served.
  • All public endpoints are read-only except a small set of writes: reviews (POST), forms (POST), contact (POST), claims (POST), marketplace inquiry (POST).
  • Nothing is open by default. Most endpoints require a scoped tenant API key (X-API-Key). A small, deliberately chosen set of endpoints is keyless because it is public-safe by design (see §2.1) — those are resolved by host and are still rate-limited.
  • Every endpoint — keyed or keyless — is subject to per-IP (and, where applicable, per-key/per-app) rate limiting; excess traffic receives 429 (see §8).
  • For keyed endpoints, include X-API-Key: gao_xxxxxx with every request.

Vertical Blueprints (the data-model layer)

A Blueprint is a platform-level recipe for a vertical. The currently available verticals are:

Blueprintschema.org @typeMonetizationGeo search
Crypto ExchangesFinancialProductaffiliate
iGaming & CasinosProductaffiliate
Home ServicesHomeAndConstructionBusinesslead_genyes
Real EstateRealEstateListinglisting_feesyes
SaaS & SoftwareSoftwareApplicationaffiliate
Local Business DirectoryLocalBusinesslead_genyes
Professional ServicesProfessionalServicelead_genyes
Health & WellnessMedicalBusinesslead_genyes
Events & VenuesEventVenuelisting_feesyes
Generic DirectoryThinglisting_fees— (default fallback)

Where a Template owns presentation (sections, theme, layout), a Blueprint owns the data model:

  • a typed field schema (fieldGroups) that describes the structured fields living inside each Listing's metadata JSON — e.g. tradingFeeSpot, supportedCoins, bedrooms, startingPrice. Each field declares its control type, whether it appears on cards, in the comparison table, as an auto-generated FAQ, and how it maps to schema.org structured data.
  • a schema.org @type (e.g. FinancialProduct, RealEstateListing, SoftwareApplication) used for listing JSON-LD.
  • a monetization engine (affiliate, lead_gen, listing_fees, community).
  • a composition describing page archetypes and nested sub-directories (e.g. electricians / HVAC under Real Estate), each of which can borrow another blueprint's schema.
  • default categories seeded when a site adopts the blueprint, and a usesGeo flag enabling location search.

A Blueprint is a lens over the existing Listing model — no Listing data is migrated. The same field schema drives the Add-Listing form, the comparison table, storefront filters/sorting, the dynamic FAQ accordion, and the additionalProperty[] loop in listing JSON-LD, with zero per-vertical code. An App may be assigned one Blueprint (App.blueprintId); when none is set, the Generic blueprint applies.

Each Blueprint also carries vertical-appropriate demo data used by the sample-content seeding flow: defaultCategories, defaultPricingTiers, and defaultListings (8–10 listings for real, recognizable businesses in that vertical whose metadata already conforms to the vertical's fieldGroups). Seeded listings and articles are created already published (not draft), so a freshly seeded property renders as a complete, live site with no per-entry activation step. This guarantees that pricing and sample listings are vertical-correct at the data layer — every API consumer (including fully custom/headless front ends) automatically receives the right pricing tiers and real sample listings for its vertical, with no front-end logic required. A crypto property never sees home-services pricing, and a home-services property never sees crypto listings.