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.
Quickstart
From API key to first numbers in five calls.
How it fits together
Partners, workspaces, accounts and credits.
Connect Meta
Let customers connect Facebook, Instagram and ads.
Webhooks
Get alerts pushed to your backend, signed.
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.
- Check your key.curl
curl https://loudpilot.app/api/v1/ping \ -H "Authorization: Bearer $KHMA_API_KEY" - 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"}' - 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}' - Let them connect Facebook and Instagram. Create a connect link and open it for the customer; they come back to your
returnUrl.curlcurl -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"}' - 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
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.
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:
{
"error": {
"code": "workspace_not_found",
"message": "Workspace not found"
}
}| code | Type | Description |
|---|---|---|
| unauthorized | 401 | Missing or invalid API key. |
| partner_suspended | 403 | Your partner account is suspended. |
| invalid_json | 400 | The body is not JSON. |
| invalid_request | 400 | The body does not match the schema; issues lists each problem. |
| invalid_goal / invalid_period | 400 | A goal or period that does not make sense — see the message. |
| workspace_not_found / goal_not_found | 404 | Not found, or not yours. |
| single_workspace | 409 | SINGLE partners can have one workspace only. |
| already_registered / not_registered | 409 | Signup already done / not done yet. |
| not_configured | 503 | The feature is not available yet on this server. |
| internal | 500 | Our 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"{
"partner": {
"name": "Upla",
"slug": "upla",
"mode": "MULTI"
}
}Workspaces
POST/workspaces
Creates the workspace on the first call, updates its name and locale afterwards. Idempotent.
| Body | Type | Description |
|---|---|---|
| externalId | string, required | Your id for this customer profile (max 191 chars). |
| name | string, required | Shown in Loudpilot and in emails. |
| locale | string | Default 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"}'{
"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.
| Body | Type | Description |
|---|---|---|
| name | string, required | Legal or display name of the customer. |
| string, required | Billing contact of the customer. | |
| country | string | ISO 3166 code, e.g. GE. |
| currency | string | ISO 4217 code for billing, default GEL. |
| acceptTerms | true, required | The 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}'{
"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"{
"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.
- Your server creates a connect link (valid for one hour).
- Your app opens it for the customer — a redirect, new tab or popup.
- Facebook asks the customer what to share with Loudpilot.
- Loudpilot sends the customer to your
returnUrlwith the result in the query string.
POST/workspaces/{externalId}/connect-links
| Body | Type | Description |
|---|---|---|
| network | "meta", required | Facebook, Instagram and Meta Ads in one step. |
| returnUrl | https URL, required | Where 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"}'{
"url": "https://loudpilot.app/connect/meta?token=…",
"expiresAt": "2026-10-03T10:00:00.000Z"
}Back on your side:
| Query parameter | Type | Description |
|---|---|---|
| loudpilot_status | connected | error | How it went. |
| loudpilot_accounts | number | With connected: how many pages, Instagram and ad accounts were saved. |
| loudpilot_reason | string | With 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"{
"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.
resultLabelis the main result (Leads, Purchases, Link clicks …);resultscounts only that kind, never mixed with reach.current.posts,organicReach,organicViewsandengagementscover posts published from Loudpilot.
curl https://loudpilot.app/api/v1/workspaces/company_42/analytics?days=30 \
-H "Authorization: Bearer $KHMA_API_KEY"{
"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
| Body | Type | Description |
|---|---|---|
| scope | "campaign" | "ads" | "posts" | One campaign, all ads together, or published posts. |
| campaignId | string | With scope campaign: an id from analytics.campaigns. |
| network | "facebook" | "instagram" | With scope posts; leave out for both. |
| metric | string | See the metrics table below. |
| target | number | Money in the account currency; percent metrics in percent (1.5 = 1.5%). |
| atMost | boolean | Optional. Defaults to true for costs, false for everything else. |
| windowDays | 1 | 7 | 30 | Rolling 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}'{
"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:
| kind | Type | Description |
|---|---|---|
| goal_off_track | critical | More than 15% past the target. |
| goal_at_risk | warning | Close to slipping. |
| goal_recovered | info | Back on target. |
| campaign_rejected | critical | Meta disapproved a campaign. |
| campaign_issues | critical | Some ads stopped delivering. |
| account_disconnected | critical | Loudpilot lost access to a page or ad account — send a new connect link. |
| post_failed | warning / critical | A post failed on some or all accounts. |
| weekly_review | info | The 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"{
"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 kind | Type | Description |
|---|---|---|
| post | applies itself | A ready post for the coming week — becomes a Planner draft. |
| repeat | applies itself | A new take on a recent best post — becomes a Planner draft. |
| goal | applies itself | A target worth watching — becomes a goal. |
| budget | manual | Change or move a daily budget; details.steps say how. |
| creative | manual | Refresh a tired ad with the given headline, text and visual. |
| pause | manual | Stop a campaign or ad that wastes money. |
| other | manual | Anything 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"{
"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
| metric | Type | Description |
|---|---|---|
| cost_per_result | campaign, ads · money | Cost per result. Cost per lead, purchase or click — whatever the campaign is optimised for. Default: at most. |
| results | campaign, ads · count | Results. Leads, purchases, clicks … in the window. Default: at least. |
| spend | campaign, ads · money | Spend. Money spent in the window. Default: at most. |
| ctr | campaign, ads · percent | Click-through rate. Clicks ÷ impressions. Default: at least. |
| cpm | campaign, ads · money | Cost per 1,000 impressions. CPM — rises when the audience gets expensive or saturated. Default: at most. |
| ad_impressions | campaign, ads · count | Impressions. How many times the ads were shown. Default: at least. |
| ad_reach | campaign, ads · count | Reach. People reached (sum of daily reach). Default: at least. |
| roas | campaign, ads · count | Return on ad spend. Purchase value ÷ spend (needs purchase tracking). Default: at least. |
| posts | posts · count | Posts published. How often you post. Default: at least. |
| reach | posts · count | Total reach. Reach of all posts in the window. Default: at least. |
| avg_reach | posts · count | Average reach per post. Reach ÷ posts. Default: at least. |
| views | posts · count | Total views. Times your posts were seen or played. Default: at least. |
| avg_views | posts · count | Average views per post. Views ÷ posts. Default: at least. |
| likes | posts · count | Likes. Likes and reactions. Default: at least. |
| comments | posts · count | Comments. Comments on your posts. Default: at least. |
| shares | posts · count | Shares. Shares and reposts. Default: at least. |
| saves | posts · count | Saves. Instagram saves. Default: at least. |
| engagements | posts · count | Engagements. Likes + comments + shares + saves. Default: at least. |
| avg_engagements | posts · count | Average engagements per post. Engagements ÷ posts. Default: at least. |
| engagement_rate | posts · percent | Engagement 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| Tool | Type | Description |
|---|---|---|
| get_overview | read | Start here. The company, its brand, plan and credits, connected Facebook/Instagram/ad accounts, open alerts, open recommendations and active strategy plans. |
| get_dossier | read | What 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_analytics | read | Ads and posts results for the last 7, 30 or 90 days with the same-length period before, daily numbers, campaigns and top posts. |
| list_posts | read | Posts in the Planner (drafts, scheduled, published, failed), newest planned date first. Optional date range (YYYY-MM-DD) and status. |
| create_post | write | Saves 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_ai | write | Loudpilot 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_post | write | Publishes 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_goals | read | Goals Loudpilot watches hourly, with the latest actual value and status (on_track, at_risk, off_track, no_data). |
| create_goal | write | A 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_alerts | read | Latest alerts: goals off track or recovered, rejected campaigns, lost access, failed posts, weekly reviews. |
| get_weekly_review | read | The latest Monday review: what happened last week and why, with recommendations (ids for apply_recommendation / dismiss_recommendation). |
| apply_recommendation | write | Post and repeat recommendations become Planner drafts, goal ones start being watched; budget, creative, pause and other ones are recorded as done. |
| dismiss_recommendation | write | Hides a recommendation from this week’s list. |
| list_plans | read | Strategy plans made by the Loudpilot strategist. |
| get_plan | read | A full plan: diagnosis, strategy, audiences, budget, ad campaigns with forecasts, posts and goals, with what was already applied. |
| create_plan | write | The 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_plan | write | Puts 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.
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.
| Action | Type | Description |
|---|---|---|
| Post caption | 1 credit | AI-written post with hashtags. |
| Image | 1 credit | Per generated image. |
| Campaign post | 1 credit | Per post in an AI campaign. |
| Blog outline | 1 credit | Per article in a series plan. |
| Blog article | 3 credits | Full article. |
| Performance summary | 1 credit | AI 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.createdwebhook. - 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