API Overview
The Public API is everything the app does, over HTTP: the composer, the agent, the CLI, the n8n node and the MCP server all go through it. It is a fork of the original project’s API, with the same core routes and several resources the original project does not have.
SDKs and integrations
Section titled “SDKs and integrations”UseNadia has its own Node.js SDK (@usenadia/node) and its own n8n node
(n8n-nodes-nadia). Neither is published to npm yet. The original project’s
packages are not a substitute: they talk to its API, not to this one.
Authentication
Section titled “Authentication”There are two ways to authenticate:
API key
Section titled “API key”Your API key lives in UseNadia under Settings → Developers, in the Access section, under API Key. Click the reveal icon to show it, then copy. You can rotate it from the same place, rotating immediately invalidates the old key, so update anything using it (scripts, n8n, MCP clients, the CLI) at the same time.
Include it in the Authorization header:
curl -H "Authorization: your-api-key" https://app.usenadia.com/api/public/v1/integrationsOAuth2 token
Section titled “OAuth2 token”If you’re building an app for other UseNadia users, use
OAuth2 Authentication to get tokens that act on
behalf of users. OAuth tokens start with pos_ and are used the same way:
curl -H "Authorization: pos_your-oauth-token" https://app.usenadia.com/api/public/v1/integrationsBase URL
Section titled “Base URL”The base URL is https://app.usenadia.com/api.
Rate limits
Section titled “Rate limits”Status codes and errors
Section titled “Status codes and errors”A successful GET, PUT or DELETE answers 200; a successful POST
answers 201. Errors carry { "msg": "…" }, except a post the platform
refuses, which carries { provider, name, error }.
| Status | Meaning |
|---|---|
400 Bad Request |
The body or a parameter is malformed (wrong shape, unknown enum, missing required field), or the platform refused the post. |
401 Unauthorized |
Authorization header is missing, or the API key is unrecognised. |
403 Forbidden |
The key is valid but may not do this (the music write routes, for instance). |
404 Not Found |
The route doesn’t exist, or the channel, post or record in the path is not in your organisation. |
409 Conflict |
A content card with that externalId already exists, or a card cannot move there yet. |
413 Payload Too Large |
Your body exceeded 50 MB on /posts, usually because images were base64-inlined instead of pre-uploaded. See Uploads troubleshooting. |
429 Too Many Requests |
You exceeded the hourly limit on POST /posts. |
5xx |
Server error, retry with exponential backoff. |
For DELETE routes, 404 always means “already deleted” and is safe to
ignore. Treat other 500 responses as real server errors: log them, retry with
exponential backoff, and don’t silently suppress them.
Terminology
Section titled “Terminology”The resources
Section titled “The resources”Create, list, re-status, repair and delete posts.
ChannelsList and connect channels, their settings and tools, the next free slot.
Media and videoUpload a file, import a URL, the direct upload flow, AI video.
AnalyticsLive platform metrics, and the history collected every 30 minutes.
Content boardOne card per video, from the idea to the numbers after publication.
AutomationsComment → DM templates, their poses on a publication, and the people who went through.
InboxRecent posts, live stories and their comments, Instagram conversations, sending a DM.
WebhooksRegister an endpoint, pick its events, verify the signature.
Hooks and musicThe library of hooks that worked and the royalty-free catalogue. Experimental.
Six of these resource groups do not exist in the original project: the content board, automations, inbox, the collected analytics, webhooks, and hooks and music. Per-platform settings for a post are on Instagram and TikTok.
Supported platforms
Section titled “Supported platforms”Three channels can be connected here. Two of them publish:
| Platform | __type |
Key settings |
|---|---|---|
instagram-standalone |
post_type, is_trial_reel, graduation_strategy, share_to_feed, collaborators, automationFlowId, automationKeywords, automationVariables |
|
| TikTok | tiktok |
content_posting_method, privacy_level, duet, stitch, comment, autoAddMusic, brand_content_toggle, brand_organic_toggle, video_made_with_ai, title |
| YouTube | youtube |
Connectable for content cards and statistics. Publishing waits on Google’s API audit |
When creating posts, the settings object must include a __type field
matching the channel’s platform.
Generate a payload
Section titled “Generate a payload”The easiest way to generate your post payloads is the composer itself: this is the same wizard the app uses to schedule posts, except that it generates the JSON payload for your API requests instead of scheduling.
Make sure you are logged in to app.usenadia.com.
Open in full screen
Quick examples
Section titled “Quick examples”Upload a video, then schedule a Reel
Section titled “Upload a video, then schedule a Reel”# Step 1: uploadcurl -X POST "https://app.usenadia.com/api/public/v1/upload" \ -H "Authorization: your-api-key" \ -F "file=@reel.mp4"
# 201 → { "id": "cm4med0001", "path": "https://media.usenadia.com/k3J9aQ2xZp.mp4", ... }
# Step 2: create the post with the uploaded mediacurl -X POST "https://app.usenadia.com/api/public/v1/posts" \ -H "Authorization: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "type": "schedule", "date": "2026-11-03T10:00:00.000Z", "shortLink": false, "tags": [], "posts": [{ "integration": { "id": "your-instagram-id" }, "value": [{ "content": "Trois choses que personne ne dit sur Malte.", "image": [{ "id": "cm4med0001", "path": "https://media.usenadia.com/k3J9aQ2xZp.mp4" }] }], "settings": { "__type": "instagram-standalone", "post_type": "post" } }] }'
# 201 → [ { "postId": "cm4post0001", "integration": "your-instagram-id" } ]Publish to TikTok immediately
Section titled “Publish to TikTok immediately”{ "type": "now", "date": "2026-11-03T10:00:00.000Z", "shortLink": false, "tags": [], "posts": [ { "integration": { "id": "your-tiktok-id" }, "value": [ { "content": "Trois choses que personne ne dit sur Malte.", "image": [{ "id": "cm4med0001", "path": "https://media.usenadia.com/k3J9aQ2xZp.mp4" }] } ], "settings": { "__type": "tiktok", "content_posting_method": "DIRECT_POST", "privacy_level": "PUBLIC_TO_EVERYONE", "duet": true, "stitch": true, "comment": true, "autoAddMusic": "no", "brand_content_toggle": false, "brand_organic_toggle": false } } ]}Schedule a story that runs an automation
Section titled “Schedule a story that runs an automation”{ "settings": { "__type": "instagram-standalone", "post_type": "story", "automationFlowId": "<template id>", "automationKeywords": ["LIEN", "LEIN", "GUIDE"], "automationVariables": { "ressource": "le guide Malte", "bouton": "Le guide", "lien": "https://…" } }}The pose is created when the post publishes, not when it is scheduled: Instagram has no media ID before then. The words and values are checked at scheduling time. See Automations.
Notifications
Section titled “Notifications”GET /notifications?page=0The organisation’s notifications, newest first, 100 per page (page is
0-indexed): a post published, a post that failed, a channel to reconnect.
Response 200:
{ "notifications": [ { "id": "a1b2c3d4-…", "content": "Your post to Instagram was published successfully", "link": null, "createdAt": "2026-10-20T10:30:00.000Z" } ], "total": 250, "page": 0, "limit": 100, "hasMore": true}For a push rather than a poll, register a webhook.