Uniflo|Documentation API
PricingDashboard
REST API · v1

Publish anywhere.
From one API call.

Uniflo exposes a unified REST API to publish across social networks, newsletters, and blogs — with built-in AI generation, scheduling, and analytics. Works with n8n, agents, and Claude via MCP.

Get API keyQuick start
Social
LinkedIn · Instagram · Facebook · TikTok
Newsletter
Mailchimp · Brevo · Listmonk · Mailerlite
Blog
Ghost · WordPress · Medium · DevTo
AI generation
Claude — brief to post in one call
Scheduling
BullMQ — precise delayed jobs
MCP server
Native tool for Claude agents

Authentication

All /api/v1/* endpoints require a Bearer token. Create keys from the dashboard under Clés API. Keys are prefixed ufk_ and hashed (SHA-256) at rest — the raw token is shown only once.

Authorization: Bearer ufk_AbCdEfGhIjKlMnOpQrStUvWxYz...

# Example with curl
curl https://app.uniflo.eu/api/v1/channels \
  -H "Authorization: Bearer ufk_xxx"
Rate limit: 600 requests/minute per key. Exceeded requests return HTTP 429 with a Retry-After: 60 header.

Base URL

https://app.uniflo.eu

All responses are application/json. Errors follow { "error": "message" }.

Endpoints

GET/api/v1/channelsList channels

Returns all active connected channels for the workspace (social, newsletter, blog, video).

RESPONSE
{
  "channels": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "provider": "linkedin",
      "type": "social",
      "name": "Reverdin Consulting",
      "capabilities": ["text", "image", "schedule"],
      "lastTestOk": true
    }
  ]
}
POST/api/v1/generateGenerate content (AI)

Generate publish-ready content from a brief. Uniflo adapts the copy to the channel style guide, brand voice, and historical performance data.

REQUEST BODY
{
  "channel_id": "3fa85f64-...",   // optional — uses its style guide
  "provider": "linkedin",          // alternative to channel_id
  "brief": {
    "topic": "Lancement de notre API publique",
    "angle": "Pour les développeurs et les agents IA",
    "tone": "professionnel",
    "keywords": ["API", "social media", "IA"],
    "cta": "Essayez gratuitement"
  }
}
RESPONSE
{
  "text": "Nous lançons l'API Uniflo...",
  "hashtags": ["API", "Marketing", "IA"],
  "altText": "Dashboard Uniflo avec graphiques d'engagement",
  "notes": "Visuel suggéré : capture d'écran du dashboard",
  "confidence": 89
}
POST/api/v1/publishPublish immediately

Publish to one or more channels. Provide text directly or let Uniflo generate from a brief. Returns a job ID — poll /v1/jobs/:id for status.

REQUEST BODY
// Option A — text direct
{
  "channels": ["<channel-uuid>"],
  "text": "Notre nouveau produit est disponible !",
  "hashtags": ["lancement", "innovation"]
}

// Option B — génération IA (the feature Ayrshare doesn't have)
{
  "channels": ["<uuid-linkedin>", "<uuid-ghost>"],
  "generate": {
    "topic": "Nouvelle feature : publication multi-canal en une requête",
    "tone": "enthousiaste"
  }
}
RESPONSE
{
  "jobId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "scheduledAt": null
}
POST/api/v1/scheduleSchedule a post

Same as /publish but with a required scheduledAt. BullMQ delays the job precisely.

REQUEST BODY
{
  "channels": ["<channel-uuid>"],
  "text": "Bon lundi ! Voici notre article de la semaine...",
  "scheduledAt": "2026-06-02T09:00:00Z",
  "generate": {
    "topic": "Tendances marketing IA en juin 2026"
  }
}
RESPONSE
{
  "jobId": "a1b2c3d4-...",
  "scheduledAt": "2026-06-02T09:00:00.000Z"
}
GET/api/v1/jobs/:idGet job status

Poll the status of a publish or schedule job. Status: pending → processing → done | partial | failed.

RESPONSE
{
  "id": "7c9e6679-...",
  "status": "done",
  "scheduledAt": null,
  "results": {
    "<channel-uuid-linkedin>": {
      "ok": true,
      "externalId": "urn:li:ugcPost:7234567890",
      "externalUrl": "https://www.linkedin.com/feed/update/..."
    },
    "<channel-uuid-ghost>": {
      "ok": false,
      "error": "Ghost API: post slug already exists"
    }
  },
  "createdAt": "2026-05-30T10:32:00.000Z",
  "updatedAt": "2026-05-30T10:32:04.000Z"
}
GET/api/v1/analytics/channels/:idChannel analytics

Aggregated 7-day engagement metrics + top posts + AI-generated style guide. Use to close the feedback loop in autonomous agents.

RESPONSE
{
  "channel": { "id": "...", "provider": "instagram", "name": "Mon Compte" },
  "window": "7d",
  "sampleSize": 32,
  "avgEngagementRate": "4.21",
  "topPosts": [
    { "externalId": "17...", "engagementRate": "7.80", "likes": 412, "reach": 5280 }
  ],
  "styleGuide": {
    "tone": ["inspirant", "éducatif"],
    "themes": ["skincare", "routine", "conseils"],
    "topHashtags": ["skincare", "beauty", "routine"],
    "bestPerformingFormat": "REEL",
    "writingStyle": "Court, punchy, émojis espacés"
  }
}
GET/api/v1/keysList API keys

List active API keys for the workspace. Requires session authentication (dashboard).

RESPONSE
{
  "keys": [
    {
      "id": "...",
      "name": "n8n-prod",
      "keyPrefix": "ufk_AbCdEf",
      "scopes": ["publish", "read"],
      "status": "active",
      "lastUsedAt": "2026-05-30T09:14:00.000Z",
      "expiresAt": null,
      "createdAt": "2026-05-28T14:00:00.000Z"
    }
  ]
}
POST/api/v1/keysCreate API key

Create a new API key. The raw token is returned once and never stored — copy it immediately.

REQUEST BODY
{
  "name": "n8n-prod",
  "scopes": ["publish", "read"],
  "expiresAt": "2027-01-01T00:00:00Z"   // optional
}
RESPONSE
{
  "id": "...",
  "name": "n8n-prod",
  "keyPrefix": "ufk_AbCdEf",
  "token": "ufk_AbCdEfGhIjKlMnOpQrStUvWxYz...",   // shown once only
  "createdAt": "2026-05-30T14:00:00.000Z"
}
DELETE/api/v1/keys/:idRevoke API key

Permanently revoke a key. All requests using this key will immediately return 401.

RESPONSE
{ "ok": true }

MCP Server for Claude

Uniflo exposes a JSON-RPC 2.0 MCP server at /api/mcp, compatible with Claude Desktop, Claude Code, and any MCP client. Add it to your config to give Claude direct access to all your connected channels.

Available tools
list_channelsList connected channels
generate_contentGenerate content from a brief
publish_postPublish immediately (text or generate)
schedule_postSchedule with scheduledAt
get_job_statusPoll job result
get_analyticsChannel metrics + style guide
claude_desktop_config.json
{
  "mcpServers": {
    "uniflo": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://app.uniflo.eu/api/mcp"],
      "env": { "MCP_API_KEY": "ufk_your_key_here" }
    }
  }
}

Quick start

Generate and publish a LinkedIn post in 3 lines:

# 1. List your channels
curl https://app.uniflo.eu/api/v1/channels \
  -H "Authorization: Bearer ufk_xxx"

# 2. Generate + publish in one call
curl -X POST https://app.uniflo.eu/api/v1/publish \
  -H "Authorization: Bearer ufk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "channels": ["<linkedin-channel-uuid>"],
    "generate": {
      "topic": "Our API is now live",
      "tone": "professional",
      "keywords": ["API", "social media automation"]
    }
  }'

# 3. Poll the job
curl https://app.uniflo.eu/api/v1/jobs/<jobId> \
  -H "Authorization: Bearer ufk_xxx"

n8n — single HTTP Request node:

Method: POST
URL: https://app.uniflo.eu/api/v1/publish
Headers: Authorization: Bearer {{ $env.UNIFLO_API_KEY }}
Body (JSON):
{
  "channels": ["{{ $json.channelId }}"],
  "text": "{{ $json.postText }}",
  "scheduledAt": "{{ $json.publishAt }}"
}
Official SDKs — coming soon

TypeScript/Node.js, Python, and a Claude Code skill are in progress. In the meantime, the REST API works with any HTTP client.

Start free — get your API key