On this page

Loudpilot Partner API

Give every customer of your product a marketing module

Your users already work in your product. With a few calls they get AI content, publishing, ad results, goals and alerts — inside your UI, while Loudpilot does the marketing work and the billing.

Base URL https://loudpilot.app/api/v1 · JSON in, JSON out · times in ISO 8601 (UTC)

Quickstart

Five calls from an API key to a customer with connected pages and live numbers.

  1. Check your key.
    curl
    curl https://loudpilot.app/api/v1/ping \
      -H "Authorization: Bearer $KHMA_API_KEY"
  2. Create a workspace for one of your customers, using your own id for it. Safe to call every time the customer opens Marketing in your app.
    curl
    curl -X POST https://loudpilot.app/api/v1/workspaces \
      -H "Authorization: Bearer $KHMA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"externalId":"company_42","name":"Arca Development"}'
  3. Register the customer once — they accept Loudpilot's terms in your UI and get a credit wallet.
    curl
    curl -X POST https://loudpilot.app/api/v1/workspaces/company_42/signup \
      -H "Authorization: Bearer $KHMA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name":"Arca Development LLC","email":"owner@arca.ge","acceptTerms":true}'
  4. Let them connect Facebook and Instagram. Create a connect link and open it for the customer; they come back to your returnUrl.
    curl
    curl -X POST https://loudpilot.app/api/v1/workspaces/company_42/connect-links \
      -H "Authorization: Bearer $KHMA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"network":"meta","returnUrl":"https://app.example.com/marketing"}'
  5. Show results in your app.
    curl
    curl https://loudpilot.app/api/v1/workspaces/company_42/analytics?days=30 \
      -H "Authorization: Bearer $KHMA_API_KEY"

How it fits together

Model
Partner (you)  — API key, SINGLE or MULTI mode, revenue share
└── Workspace  — one per customer profile, addressed by YOUR externalId
    ├── Account   — the paying customer: terms accepted, credit wallet
    ├── Channels  — Facebook Pages, Instagram accounts, Meta ad accounts
    ├── Analytics — ad and post results
    └── Goals → Alerts → your webhook
  • Partner — your product. SINGLE partners have one workspace (a company using Loudpilot inside its own tools). MULTI partners resell: every company, agent or seller in your product gets its own workspace.
  • Workspace — you always address it by externalId, your own id. You can only ever reach the workspaces you created.
  • Account — created by signup. The customer pays Loudpilot for credits directly; you earn a share of every purchase.
  • Channels — connected by the customer through a connect link. Loudpilot uses one verified Meta app for everyone, so customers never handle API keys.

Authentication

Send your key as a bearer token on every request. Keys start with lp_live_, are shown once when we issue them and are stored by us only as a hash.

http
Authorization: Bearer lp_live_…

Call the API from your server only — never from a browser or a mobile app. Need a key, a second key or a rotation? Write to us.

Errors

Errors use HTTP status codes and always the same body:

json
{
  "error": {
    "code": "workspace_not_found",
    "message": "Workspace not found"
  }
}
codeTypeDescription
unauthorized401Missing or invalid API key.
partner_suspended403Your partner account is suspended.
invalid_json400The body is not JSON.
invalid_request400The body does not match the schema; issues lists each problem.
invalid_goal / invalid_period400A goal or period that does not make sense — see the message.
workspace_not_found / goal_not_found404Not found, or not yours.
single_workspace409SINGLE partners can have one workspace only.
already_registered / not_registered409Signup already done / not done yet.
not_configured503The feature is not available yet on this server.
internal500Our fault. Safe to retry with backoff.

Ping

GET/ping

Checks the key and tells you how Loudpilot sees you.

curl https://loudpilot.app/api/v1/ping \
  -H "Authorization: Bearer $KHMA_API_KEY"
Response
{
  "partner": {
    "name": "Upla",
    "slug": "upla",
    "mode": "MULTI"
  }
}

Workspaces

POST/workspaces

Creates the workspace on the first call, updates its name and locale afterwards. Idempotent.

BodyTypeDescription
externalIdstring, requiredYour id for this customer profile (max 191 chars).
namestring, requiredShown in Loudpilot and in emails.
localestringDefault content language, e.g. ka, en, ru.
curl -X POST https://loudpilot.app/api/v1/workspaces \
  -H "Authorization: Bearer $KHMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"externalId":"company_42","name":"Arca Development","locale":"ka"}'
Response
{
  "workspace": {
    "externalId": "company_42",
    "name": "Arca Development",
    "locale": "ka",
    "registered": false,
    "account": null,
    "createdAt": "2026-10-03T09:00:00.000Z"
  }
}

GET/workspaces

Your workspaces, newest first (up to 200).

GET/workspaces/{externalId}

One workspace, with its account once registered.

Sign up a customer

POST/workspaces/{externalId}/signup

Creates the paying account for the workspace. Show Loudpilot's Terms and Privacy Policy in your UI and send acceptTerms: true only after the customer agreed.

BodyTypeDescription
namestring, requiredLegal or display name of the customer.
emailstring, requiredBilling contact of the customer.
countrystringISO 3166 code, e.g. GE.
currencystringISO 4217 code for billing, default GEL.
acceptTermstrue, requiredThe customer accepted the terms.
curl -X POST https://loudpilot.app/api/v1/workspaces/company_42/signup \
  -H "Authorization: Bearer $KHMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Arca Development LLC","email":"owner@arca.ge","acceptTerms":true}'
Response
{
  "workspace": {
    "externalId": "company_42",
    "name": "Arca Development",
    "locale": "ka",
    "registered": true,
    "account": {
      "name": "Arca Development LLC",
      "email": "owner@arca.ge",
      "currency": "GEL",
      "creditBalance": 0
    },
    "createdAt": "2026-10-03T09:00:00.000Z"
  }
}

Credits

GET/workspaces/{externalId}/credits

Balance and the last 50 movements, to show the wallet inside your app.

curl https://loudpilot.app/api/v1/workspaces/company_42/credits \
  -H "Authorization: Bearer $KHMA_API_KEY"
Response
{
  "balance": 287,
  "currency": "GEL",
  "entries": [
    {
      "amount": -1,
      "reason": "AI_TEXT",
      "note": "Post caption",
      "createdAt": "2026-10-03T09:30:00.000Z"
    },
    {
      "amount": 300,
      "reason": "PURCHASE",
      "note": "Starter plan",
      "createdAt": "2026-10-01T08:00:00.000Z"
    }
  ]
}

Connect Meta

Customers connect their own Facebook Pages, Instagram professional accounts and Meta ad accounts. They sign in to Facebook, pick what to share and land back in your app — they never see a Loudpilot login.

  1. Your server creates a connect link (valid for one hour).
  2. Your app opens it for the customer — a redirect, new tab or popup.
  3. Facebook asks the customer what to share with Loudpilot.
  4. Loudpilot sends the customer to your returnUrl with the result in the query string.

POST/workspaces/{externalId}/connect-links

BodyTypeDescription
network"meta", requiredFacebook, Instagram and Meta Ads in one step.
returnUrlhttps URL, requiredWhere the customer goes afterwards. Existing query parameters are kept.
curl -X POST https://loudpilot.app/api/v1/workspaces/company_42/connect-links \
  -H "Authorization: Bearer $KHMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"network":"meta","returnUrl":"https://app.example.com/marketing"}'
Response
{
  "url": "https://loudpilot.app/connect/meta?token=…",
  "expiresAt": "2026-10-03T10:00:00.000Z"
}

Back on your side:

Query parameterTypeDescription
loudpilot_statusconnected | errorHow it went.
loudpilot_accountsnumberWith connected: how many pages, Instagram and ad accounts were saved.
loudpilot_reasonstringWith error: cancelled, expired, nothing_shared, meta_error, not_configured, workspace_not_found.

Ad results are read right after connecting and then every hour; post results every 30 minutes.

Channels

GET/workspaces/{externalId}/channels

What the customer connected. status is active, expired (ask the customer to connect again with a new link) or revoked. Tokens never leave Loudpilot.

curl https://loudpilot.app/api/v1/workspaces/company_42/channels \
  -H "Authorization: Bearer $KHMA_API_KEY"
Response
{
  "channels": [
    {
      "id": "cm1…",
      "network": "facebook",
      "name": "Arca Development",
      "handle": null,
      "status": "active",
      "error": null,
      "connectedAt": "2026-10-03T09:10:00.000Z"
    },
    {
      "id": "cm2…",
      "network": "instagram",
      "name": "Arca Development",
      "handle": "arca.ge",
      "status": "active",
      "error": null,
      "connectedAt": "2026-10-03T09:10:00.000Z"
    },
    {
      "id": "cm3…",
      "network": "meta_ads",
      "name": "Arca Ads",
      "handle": null,
      "status": "active",
      "error": null,
      "connectedAt": "2026-10-03T09:10:00.000Z"
    }
  ]
}

Analytics

GET/workspaces/{externalId}/analytics?days=30

The numbers behind the Loudpilot dashboard for 7, 30 or 90 days, plus the same-length period before it so you can show change. Days follow the ad account's time zone.

  • resultLabel is the main result (Leads, Purchases, Link clicks …); results counts only that kind, never mixed with reach.
  • current.posts, organicReach, organicViews and engagements cover posts published from Loudpilot.
curl https://loudpilot.app/api/v1/workspaces/company_42/analytics?days=30 \
  -H "Authorization: Bearer $KHMA_API_KEY"
Response
{
  "period": {
    "days": 30,
    "from": "2026-09-04",
    "to": "2026-10-03",
    "timeZone": "Asia/Tbilisi"
  },
  "currency": "GEL",
  "resultLabel": "Leads",
  "current": {
    "spend": 900,
    "impressions": 330000,
    "clicks": 2400,
    "results": 120,
    "revenue": 0,
    "posts": 12,
    "organicReach": 18400,
    "organicViews": 25100,
    "engagements": 940
  },
  "previous": {
    "spend": 900,
    "impressions": 330000,
    "clicks": 2400,
    "results": 60,
    "revenue": 0,
    "posts": 9,
    "organicReach": 15100,
    "organicViews": 20300,
    "engagements": 710
  },
  "daily": [
    {
      "date": "2026-10-03",
      "spend": 30,
      "results": 4,
      "organicReach": 650,
      "engagements": 31
    }
  ],
  "campaigns": [
    {
      "id": "cm9…",
      "name": "Lead Gen — Tbilisi",
      "status": "active",
      "objective": "OUTCOME_LEADS",
      "dailyBudget": 20,
      "lifetimeBudget": null,
      "currency": "GEL",
      "spend": 600,
      "impressions": 90000,
      "clicks": 1800,
      "results": 120,
      "resultLabel": "Leads",
      "costPerResult": 5,
      "ctr": 0.02
    }
  ],
  "topPosts": [
    {
      "postId": "cp1…",
      "network": "instagram",
      "text": "Pistachio week…",
      "date": "2026-09-28",
      "reach": 2400,
      "engagements": 180,
      "url": "https://instagram.com/p/…"
    }
  ]
}

Goals

A goal is a target Loudpilot checks every hour, over complete days. Within 15% on the wrong side it is at_risk, beyond that off_track. Each change raises an alert.

POST/workspaces/{externalId}/goals

BodyTypeDescription
scope"campaign" | "ads" | "posts"One campaign, all ads together, or published posts.
campaignIdstringWith scope campaign: an id from analytics.campaigns.
network"facebook" | "instagram"With scope posts; leave out for both.
metricstringSee the metrics table below.
targetnumberMoney in the account currency; percent metrics in percent (1.5 = 1.5%).
atMostbooleanOptional. Defaults to true for costs, false for everything else.
windowDays1 | 7 | 30Rolling window, default 7.
curl -X POST https://loudpilot.app/api/v1/workspaces/company_42/goals \
  -H "Authorization: Bearer $KHMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scope":"campaign","campaignId":"cm9…","metric":"cost_per_result","target":5,"windowDays":7}'
Response
{
  "goal": {
    "id": "cg1…",
    "scope": "campaign",
    "campaignId": "cm9…",
    "network": null,
    "metric": "cost_per_result",
    "atMost": true,
    "target": 5,
    "windowDays": 7,
    "active": true,
    "status": "on_track",
    "actual": 4.2,
    "checkedAt": "2026-10-03T09:15:00.000Z"
  }
}

GET/workspaces/{externalId}/goals

All goals with their latest status and actual value.

DELETE/workspaces/{externalId}/goals/{goalId}

Alerts

Raised when a goal changes status, and for things that need a human:

kindTypeDescription
goal_off_trackcriticalMore than 15% past the target.
goal_at_riskwarningClose to slipping.
goal_recoveredinfoBack on target.
campaign_rejectedcriticalMeta disapproved a campaign.
campaign_issuescriticalSome ads stopped delivering.
account_disconnectedcriticalLoudpilot lost access to a page or ad account — send a new connect link.
post_failedwarning / criticalA post failed on some or all accounts.
weekly_reviewinfoThe Monday review is ready — fetch it from /reviews/latest.

GET/workspaces/{externalId}/alerts?unread=true

curl https://loudpilot.app/api/v1/workspaces/company_42/alerts?unread=true \
  -H "Authorization: Bearer $KHMA_API_KEY"
Response
{
  "alerts": [
    {
      "id": "ca1…",
      "kind": "goal_off_track",
      "severity": "critical",
      "title": "Cost per result above target — Lead Gen — Tbilisi",
      "body": "₾7.20 for the last 7 days vs target at most ₾5.00 (44% above). Click-through fell 31% — the creative may be tiring. Try a new image or first line.",
      "url": "https://loudpilot.app/app/dashboard/ads/cm9…",
      "createdAt": "2026-10-03T10:00:00.000Z",
      "read": false,
      "goalId": "cg1…"
    }
  ]
}

POST/workspaces/{externalId}/alerts/read

Marks alerts read — the ones in ids, or all unread ones if you send {}.

Weekly review

Every Monday (from 07:00 in the workspace's time zone) Loudpilot reviews the last Monday–Sunday: ads, posts, goals and alerts against the week before, with the company dossier in mind. You get a weekly_review alert, then fetch the review and show its recommendations in your app.

Recommendation kindTypeDescription
postapplies itselfA ready post for the coming week — becomes a Planner draft.
repeatapplies itselfA new take on a recent best post — becomes a Planner draft.
goalapplies itselfA target worth watching — becomes a goal.
budgetmanualChange or move a daily budget; details.steps say how.
creativemanualRefresh a tired ad with the given headline, text and visual.
pausemanualStop a campaign or ad that wastes money.
othermanualAnything else, with steps.

GET/workspaces/{externalId}/reviews/latest

curl https://loudpilot.app/api/v1/workspaces/company_42/reviews/latest \
  -H "Authorization: Bearer $KHMA_API_KEY"
Response
{
  "review": {
    "id": "cw1…",
    "weekStart": "2026-09-28",
    "weekEnd": "2026-10-04",
    "headline": "Leads got 30% cheaper after the video ads took over",
    "summary": "…",
    "wins": [
      {
        "text": "Family video ad drove 41 leads at ₾3.40",
        "evidence": "₾140 spend, CTR 2.3%"
      }
    ],
    "issues": [
      {
        "text": "Only one post this week",
        "evidence": "1 post vs 3 the week before"
      }
    ],
    "createdAt": "2026-10-05T04:00:00.000Z",
    "recommendations": [
      {
        "id": "cr1…",
        "kind": "post",
        "title": "Post an evening reel of the park view on Thursday",
        "why": "Reels reached 1.8× your average; evenings 1.6×.",
        "impact": "high",
        "status": "open",
        "details": {
          "post": {
            "date": "2026-10-08",
            "time": "19:00",
            "network": "INSTAGRAM",
            "format": "Reel",
            "caption": "…",
            "hashtags": [
              "arca"
            ],
            "visual": "…"
          }
        },
        "appliedRef": null
      }
    ]
  }
}

POST/workspaces/{externalId}/recommendations/{id}/apply

Posts and goals are created (appliedRef is their id); manual kinds are recorded as done. 409 if it was already handled.

POST/workspaces/{externalId}/recommendations/{id}/dismiss

Goal metrics

metricTypeDescription
cost_per_resultcampaign, ads · moneyCost per result. Cost per lead, purchase or click — whatever the campaign is optimised for. Default: at most.
resultscampaign, ads · countResults. Leads, purchases, clicks … in the window. Default: at least.
spendcampaign, ads · moneySpend. Money spent in the window. Default: at most.
ctrcampaign, ads · percentClick-through rate. Clicks ÷ impressions. Default: at least.
cpmcampaign, ads · moneyCost per 1,000 impressions. CPM — rises when the audience gets expensive or saturated. Default: at most.
ad_impressionscampaign, ads · countImpressions. How many times the ads were shown. Default: at least.
ad_reachcampaign, ads · countReach. People reached (sum of daily reach). Default: at least.
roascampaign, ads · countReturn on ad spend. Purchase value ÷ spend (needs purchase tracking). Default: at least.
postsposts · countPosts published. How often you post. Default: at least.
reachposts · countTotal reach. Reach of all posts in the window. Default: at least.
avg_reachposts · countAverage reach per post. Reach ÷ posts. Default: at least.
viewsposts · countTotal views. Times your posts were seen or played. Default: at least.
avg_viewsposts · countAverage views per post. Views ÷ posts. Default: at least.
likesposts · countLikes. Likes and reactions. Default: at least.
commentsposts · countComments. Comments on your posts. Default: at least.
sharesposts · countShares. Shares and reposts. Default: at least.
savesposts · countSaves. Instagram saves. Default: at least.
engagementsposts · countEngagements. Likes + comments + shares + saves. Default: at least.
avg_engagementsposts · countAverage engagements per post. Engagements ÷ posts. Default: at least.
engagement_rateposts · percentEngagement rate. Engagements ÷ reach. Default: at least.

Windows: 1 (yesterday), 7 (last 7 days), 30 (last 30 days). Ads are judged on complete days; posts once they are a day old. Totals for campaigns that ran only part of the window are compared with a prorated target.

MCP for AI assistants

Loudpilot is an MCP server: Claude, ChatGPT, Cursor, VS Code, Codex and other assistants can read results and work in Loudpilot for a signed-in user. Server URL https://loudpilot.app/api/mcp (Streamable HTTP).

  • Sign-in (OAuth 2.1) — apps that support it register themselves, open Loudpilot in the browser, and the user picks the company and presses Allow. Discovery at /.well-known/oauth-protected-resource; PKCE (S256) and refresh tokens.
  • Personal token — for apps without sign-in, create one in Loudpilot → AI assistants and send it as Authorization: Bearer lp_pat_….
  • The assistant acts as that user in one workspace, with the same roles as in the app. Up to 120 calls a minute.
claude mcp add --transport http khma https://loudpilot.app/api/mcp
ToolTypeDescription
get_overviewreadStart here. The company, its brand, plan and credits, connected Facebook/Instagram/ad accounts, open alerts, open recommendations and active strategy plans.
get_dossierreadWhat Loudpilot knows about the company: profile from its website, and the audit of 12 months of posts and ads (what works, what does not, best times, never-again list).
get_analyticsreadAds and posts results for the last 7, 30 or 90 days with the same-length period before, daily numbers, campaigns and top posts.
list_postsreadPosts in the Planner (drafts, scheduled, published, failed), newest planned date first. Optional date range (YYYY-MM-DD) and status.
create_postwriteSaves a post in the Planner. Without "schedule" it is a draft (never published automatically). With schedule=true and a future scheduledAt it is published automatically to the connected accounts of the chosen networks.
write_post_with_aiwriteLoudpilot writes an on-brand caption and hashtags using the company dossier (what worked, what to avoid) and saves it as a Planner draft. Costs 1 credit.
publish_postwritePublishes a saved post right now to the connected Facebook Page / Instagram account of its channels. Accounts that already have it are skipped, so this also retries failures.
list_goalsreadGoals Loudpilot watches hourly, with the latest actual value and status (on_track, at_risk, off_track, no_data).
create_goalwriteA target Loudpilot checks every hour and alerts on. Metrics: cost_per_result (campaign/ads), results (campaign/ads), spend (campaign/ads), ctr (campaign/ads), cpm (campaign/ads), ad_impressions (campaign/ads), ad_reach (campaign/ads), roas (campaign/ads), posts (posts), reach (posts), avg_reach (posts), views (posts), avg_views (posts), likes (posts), comments (posts), shares (posts), saves (posts), engagements (posts), avg_engagements (posts), engagement_rate (posts). Percent metrics in percent (2 = 2%).
list_alertsreadLatest alerts: goals off track or recovered, rejected campaigns, lost access, failed posts, weekly reviews.
get_weekly_reviewreadThe latest Monday review: what happened last week and why, with recommendations (ids for apply_recommendation / dismiss_recommendation).
apply_recommendationwritePost and repeat recommendations become Planner drafts, goal ones start being watched; budget, creative, pause and other ones are recorded as done.
dismiss_recommendationwriteHides a recommendation from this week’s list.
list_plansreadStrategy plans made by the Loudpilot strategist.
get_planreadA full plan: diagnosis, strategy, audiences, budget, ad campaigns with forecasts, posts and goals, with what was already applied.
create_planwriteThe Loudpilot strategist turns a business goal into a plan (audiences, budget, ad campaigns with forecasts from the account's own history, two weeks of posts, goals) using the company dossier. Takes about a minute. Costs 5 credits.
apply_planwritePuts a plan to work: "posts" adds its posts to the Planner as drafts at their dates; "goals" starts watching its goals.

Webhooks

Give us an HTTPS endpoint and we send every new alert of your workspaces as it happens, signed with a secret only you and Loudpilot know. Answer with any 2xx; otherwise we retry every minute for up to two days.

POST your endpoint
Content-Type: application/json
X-Loudpilot-Timestamp: 1791010000
X-Loudpilot-Signature: sha256=5f1c…

{
  "type": "alert.created",
  "workspace": {
    "externalId": "company_42"
  },
  "alert": {
    "id": "ca1…",
    "kind": "goal_off_track",
    "severity": "critical",
    "title": "Cost per result above target — Lead Gen — Tbilisi",
    "body": "₾7.20 for the last 7 days vs target at most ₾5.00 (44% above).",
    "url": "https://loudpilot.app/app/dashboard/ads/cm9…",
    "createdAt": "2026-10-03T10:00:00.000Z"
  }
}

Verify every call: the signature is HMAC-SHA256 of {timestamp}.{raw body} with your webhook secret. Reject calls older than five minutes.

import { createHmac, timingSafeEqual } from 'node:crypto'

export function verifyLoudpilot(rawBody, headers, secret) {
  const ts = headers['x-loudpilot-timestamp']
  const given = (headers['x-loudpilot-signature'] ?? '').replace('sha256=', '')
  if (!ts || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false
  const expected = createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex')
  return given.length === expected.length && timingSafeEqual(Buffer.from(given), Buffer.from(expected))
}

Alerts are also emailed to the customer's owners and admins who use Loudpilot directly; for your workspaces the webhook is the channel, so you decide how to show them.

Credits & revenue share

Customers pay Loudpilot for plans and credit packs; AI actions spend credits and are charged only when the result is delivered. You receive your agreed share of every purchase made by customers you brought.

ActionTypeDescription
Post caption1 creditAI-written post with hashtags.
Image1 creditPer generated image.
Campaign post1 creditPer post in an AI campaign.
Blog outline1 creditPer article in a series plan.
Blog article3 creditsFull article.
Performance summary1 creditAI summary of the dashboard.

Publishing, analytics, goals, alerts and webhooks do not use credits.

Changelog

  • 2026-10-03 — MCP server with OAuth sign-in. Weekly review and recommendations. Connect links, channels, analytics, goals, alerts and the alert.created webhook.
  • 2026-10-02 — Workspaces, signup and credits.

Coming next: creating and scheduling posts, AI content and ad plans through the API. Tell us what you need