Skip to content

Channels

What the app calls a channel, the API calls an integration: one connected social account. Its id is what every other route takes as integrationId or integration.

GET /integrations your channels
GET /social/{integration} start connecting one (OAuth URL)
GET /is-connected check the API key
GET /integration-settings/{id} rules, maximum length, settings schema, tools
POST /integration-trigger/{id} run a provider tool
GET /find-slot/{id} next free slot of the channel
GET /integrations/{id}/posting-times the channel's slots
PUT /integrations/{id}/posting-times replace the channel's slots
GET /workspaces your workspaces and their channels
GET /groups deprecated alias of /workspaces
DELETE /integrations/{id} disconnect
GET /integrations
Parameter Required Description
workspace No Only the channels of this workspace (an id returned by GET /workspaces)
group No Deprecated: same effect as workspace

Response 200:

[
{
"id": "cm4ean69r0003w8w1cdomox9n",
"name": "maltaexpat",
"identifier": "instagram-standalone",
"picture": "https://media.usenadia.com/avatar.jpg",
"disabled": false,
"profile": "maltaexpat",
"workspace": { "id": "cm9w0rk5p0001w8w1a2b3c4d5", "name": "Malta Expat" },
"customer": { "id": "cm9w0rk5p0001w8w1a2b3c4d5", "name": "Malta Expat" }
}
]
Field Type Description
id string The channel id
name string As shown in the app
identifier string The platform: instagram-standalone, tiktok or youtube
picture string | null Avatar URL
disabled boolean Disconnected, or over the plan
profile string | null The handle on the platform
workspace object The channel’s workspace (every channel has exactly one): id, name
customer object Deprecated: same value as workspace, kept for the published SDKs
GET /social/{integration}

Returns the OAuth URL to send the person to. Connecting is a browser dance: the person authorises on the platform, which sends them back to UseNadia, and the channel appears in the list above.

Parameter In Required Description
integration path Yes instagram-standalone, tiktok or youtube
refresh query No An existing channel id: the flow refreshes its token instead of creating a channel

Response 200:

{ "url": "https://www.instagram.com/oauth/authorize?client_id=…&state=…" }

The state behind the URL lives one hour. 400 when the identifier is unknown (Integration not allowed); 500 when the platform’s URL could not be generated, which is what happens for a registered platform that has no credentials here.

GET /is-connected

Answers { "connected": true } with a valid key, 401 without. Useful as a smoke test of a configuration; the MCP session and the CLI do it for you.

GET /integration-settings/{id}

Response 200:

{
"output": {
"rules": "Instagram should have at least one attachment, if it's a story, it can have only one picture",
"maxLength": 2200,
"settings": { "type": "object", "properties": { "post_type": { … } } },
"tools": []
}
}
Field Description
rules The posting rules of the platform, in a sentence
maxLength Characters allowed in the text, verification taken into account
settings The JSON schema of the provider settings, or the string No additional settings required when the platform has none
tools The provider tools POST /integration-trigger/{id} can run: methodName, description, dataSchema (key, type, description)

404 when the channel is not yours.

POST /integration-trigger/{id}
{ "methodName": "audioSearch", "data": { "q": "summer" } }

Runs a tool the provider exposes and answers 201 with { "output": … }, the raw provider answer. 404 when the channel is not yours or the tool does not exist on its platform (Tool not found); 401 when the platform’s token expired and could not be refreshed, in which case the channel is disconnected.

GET /find-slot/{id}

Walks the channel’s time slots from now, day by day, keeping only those that fire on that weekday, and answers the first one with no post scheduled, 200:

{ "date": "2026-10-21T10:00:00.000Z" }

400 when the channel has no slot (or no day checked).

GET /integrations/{id}/posting-times
PUT /integrations/{id}/posting-times

A slot is a time and the weekdays it fires on, in UTC: time in minutes after midnight UTC (0 to 1439, 18:30 UTC = 1110), days from 0 (Sunday) to 6 (Saturday), no days = every day. GET answers, and PUT takes { "times": [...] } in the body then answers, 200:

{
"integrationId": "cm4ean69r0003w8w1cdomox9n",
"times": [
{ "time": 480, "days": [1, 3, 5] },
{ "time": 1110 }
]
}

PUT replaces all the channel’s slots; posts already scheduled do not move. 404 on a channel that is not yours.

GET /workspaces

Answers 200 with your workspaces, oldest first. A workspace is a folder of channels: every channel is in exactly one workspace, and every organization has at least one (see Workspaces and scope).

[
{
"id": "cm9w0rk5p0001w8w1a2b3c4d5",
"name": "Malta Expat",
"channels": ["cm4ean69r0003w8w1cdomox9n"],
"type": "BUSINESS",
"logo": "https://uploads.usenadia.com/2026/10/28/logo.png",
"website": "https://maltaexpat.com",
"country": "MT",
"timezone": "Europe/Malta",
"about": "Guides for expats moving to Malta. Friendly, practical tone."
}
]
Field Type Description
id string The workspace id, what GET /integrations?workspace= and GET /posts?workspace= take
name string As shown in the app
channels string[] The ids of the workspace’s channels
type string PERSONAL, BUSINESS or CLIENT
logo string | null The URL of the logo
website string | null The brand’s website
country string | null The audience’s country, ISO 3166-1 alpha-2 (MT)
timezone string | null The workspace’s time zone, IANA (Europe/Malta)
about string | null Brand, audience, tone: the context an agent reads before writing for this workspace

A field nobody filled in is null. Creating, renaming or deleting a workspace, filling in its context and moving a channel into one is done in the app (Settings → Workspaces).

DELETE /integrations/{id}

Deletes the channel and every post scheduled on it. Response 200: the channel row. 404 when it is not yours.