Appearance
meta
11 endpoints.
GET /api/v1/meta/config
Get Meta Config
The Meta app credentials in force here, and which layer supplied them.
Not "the tenant's" any more: resolve reads the tenant overlay, then the site's App Settings row, then the env, and source says which one answered. The redundant Tenant fetch that used to open this function went with the rewrite — resolve already loads it.
200 — Successful Response
json
{}PUT /api/v1/meta/config
Save Meta Config
Save Meta Ads configuration for the tenant. LEGACY — prefer App Settings.
Kept because it is the only per-TENANT override (App Settings → Meta Ads is per site, which is the right scope for a developer app and the scope the LinkedIn app uses). It had no UI at all between the /social/* retirements and 2026-09-11; meta_settings.resolve still reads what it writes, and still prefers it over the site row, so an agency that genuinely needs one tenant on its own Meta app can still get there by calling this.
Nothing writes it today — no tenant in any of the four schemas has a meta_config key.
Request body
json
{
"properties": {
"meta_app_id": {
"type": "string",
"title": "Meta App Id"
},
"meta_app_secret": {
"type": "string",
"title": "Meta App Secret"
},
"meta_redirect_uri": {
"type": "string",
"title": "Meta Redirect Uri"
}
},
"type": "object",
"required": [
"meta_app_id",
"meta_app_secret",
"meta_redirect_uri"
],
"title": "MetaConfigRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/meta/accounts
List Accounts
200 — Successful Response
json
{}GET /api/v1/meta/pages
List All Pages
Every Facebook Page the caller's connected ad accounts can reach, once each.
2026-09-09, owner: "in the new ad creative process, remove the selection of ad account and replace it with facebook page selection". Every other Page picker in this app is per-ad-account (/lead-ads/pages/{account_id}, /creatives/pages/{account_id}) because a campaign picks the account first — a creative does not pick one at all now, so it needs the Pages without being told where to look.
Each Page carries the ad account a run made for it should be FILED under. Every account on this token reaches every Page, so "which account" is a real question: the answer is the account that names this Page as its own (the "Use as account's Page" action on /g/ad-pages), and failing that the first account that can reach it, which is what the account picker would have offered anyway.
Reads the same Redis-cached page lists /g/ad-pages does, so this is normally no Graph traffic at all.
200 — Successful Response
json
{}GET /api/v1/meta/accounts/{account_id}/ads
List Account Ads
Local synced ads for one account — feeds the cascade Ad selector.
Tenant + account scoped; reads the mirrored ads table (not live Meta).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
account_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/meta/connect
Connect Meta
Return Meta OAuth URL for the frontend to redirect to.
200 — Successful Response
json
{}GET /api/v1/meta/callback
Meta Callback
Handle Meta OAuth callback - exchange code for token, discover ad accounts.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
code | query | yes | string | |
state | query | no | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/meta/accounts/{account_id}
Delete Account
Soft-delete a Meta ad account.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
account_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/meta/sync-status
Sync Status
Get sync status for all accounts.
200 — Successful Response
json
{}POST /api/v1/meta/accounts/{account_id}/sync
Trigger Sync
Manually trigger a sync for a specific account.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
account_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/meta/accounts/sync-all
Sync All Accounts
Sync all accounts for the current tenant.
200 — Successful Response
json
{}