kreatoai/Documentation API

Publication multi-réseaux

POST /v1/posts publie le même contenu sur plusieurs réseaux en un seul appel — immédiatement ou à une date programmée. L'appel rend la main tout de suite (202) : la publication se fait en tâche de fond, chaque réseau vous est notifié par webhook et consultable via GET /v1/posts/:id.

Principe

POST
/v1/posts

Créer une publication (immédiate ou programmée)

GET
/v1/posts

Lister les publications récentes

GET
/v1/posts/:id

État détaillé, réseau par réseau

PATCH
/v1/posts/:id

Modifier une publication programmée

DELETE
/v1/posts/:id

Annuler une publication programmée

Scope requis : publish:posts (présent sur toute clé créée depuis le 19 juillet 2026 — les clés antérieures reçoivent 403 insufficient_scope, créez-en une nouvelle). Réseaux : facebook, instagram, linkedin, tiktok et youtube ; le compte correspondant doit être relié à votre espace de travail.

Si vous avez connecté plusieurs comptes d'un même réseau (deux pages Facebook, deux comptes TikTok…), une cible peut désigner le compte exact : { "platform": "facebook", "channelId": "…" }. Voir Comptes connectés pour obtenir ces identifiants.

Créer une publication

curl -X POST https://api.kreatoai.com/v1/posts \
  -H "x-api-key: sk-kre-v1-votre_cle" \
  -H "Content-Type: application/json" \
  -d '{
    "targets": ["facebook", "linkedin"],
    "content": "Notre nouvelle offre est en ligne !",
    "mediaUrls": ["https://media.kreatoai.com/abc.jpg"],
    "idempotencyKey": "post-lancement-2026-07-19"
  }'

Champs : targets (1 à 20 cibles, sans doublon — un nom de réseau ou un objet { platform, channelId }), content (texte, jusqu'à 63 206 caractères — les bornes plus strictes de chaque réseau sont vérifiées par cible), mediaUrls (0 à 10 URLs https publiques — hébergez vos fichiers via /v1/media), scheduledAt (ISO 8601, optionnel — absent = publication immédiate), idempotencyKey (optionnel, voir plus bas). Un PDF part sur LinkedIn en carrousel document, tel quel : seul dans mediaUrls, avec LinkedIn pour seule cible. Hébergez-le avec /v1/media (25 Mo au plus), ou donnez l'adresse https publique où il est déjà en ligne (100 Mo au plus, la limite de LinkedIn).

// 202 Accepted
{
  "id": "9f1c8b2e-…",
  "status": "processing",        // ou "scheduled" si scheduledAt est fourni
  "scheduledAt": null,
  "createdAt": "2026-07-19T14:30:00.000Z",
  "targets": [
    { "platform": "facebook", "accountId": "a3f27c9e-…", "accountName": "Campus Plus",
      "status": "pending", "externalPostId": null,
      "postUrl": null, "failReason": null, "failType": null, "completedAt": null },
    { "platform": "linkedin", "accountId": "c04e91a7-…", "accountName": "Nafiou Tino",
      "status": "pending", "externalPostId": null,
      "postUrl": null, "failReason": null, "failType": null, "completedAt": null }
  ]
}

accountId identifie le compte exact atteint par chaque cible — décisif quand plusieurs comptes du même réseau sont connectés. Il vaut null sur les publications antérieures au multi-comptes.

Fichier déposé plus tard (awaitMedia)

Quand le fichier est sur le téléphone ou l'ordinateur d'une personne, hors de portée de votre programme : créez la publication avec "awaitMedia": true et sans mediaUrls. Elle est enregistrée en attente, et la réponse porte un lien de dépôt à donner à la personne. Dès qu'elle y dépose son fichier (vidéo jusqu'à 512 Mo), la publication part seule, tout de suite ou à scheduledAt.

// POST /v1/posts
{ "targets": ["tiktok"], "content": "Ma vidéo du jour", "awaitMedia": true }

// 202 Accepted
{
  "id": "e499086e-…",
  "status": "awaiting_media",
  "mediaUploadUrl": "https://kreatoai.com/envoyer/…",
  "mediaUploadExpiresAt": "2026-10-09T11:13:37.157Z",   // le lien vaut 7 jours
  …
}

awaitMedia avec des mediaUrls renvoie 400 await_media_with_media_urls. Si votre programme a lui-même accès au fichier, préférez l'envoi direct : POST /v1/media/upload-url.

Même fichier sur d'autres comptes, à d'autres heures : créez la première publication avec awaitMedia, puis chacune des suivantes avec "sameMediaAs": "<id de la première>", sans awaitMedia ni mediaUrls. Elles renvoient le même lien de dépôt : la personne dépose son fichier une seule fois, et chaque publication part à son heure. Pour plusieurs comptes à la même heure, une seule publication avec plusieurs targets suffit.

// 1. YouTube à midi
{ "targets": ["youtube"], "content": "Ma vidéo du jour", "awaitMedia": true,
  "scheduledAt": "2026-10-07T12:00:00+02:00" }
// → { "id": "e499086e-…", "mediaUploadUrl": "https://kreatoai.com/envoyer/…", … }

// 2. TikTok à 13 h, le même fichier
{ "targets": ["tiktok"], "content": "Ma vidéo du jour", "sameMediaAs": "e499086e-…",
  "scheduledAt": "2026-10-07T13:00:00+02:00" }
// → le même mediaUploadUrl, et "sameMediaAs": "e499086e-…"

sameMediaAs qui ne désigne pas une publication de l'espace encore en attente de son fichier renvoie 400 same_media_post_not_waiting.

Statuts

Statut globalSignification
scheduledProgrammée, pas encore partie
processingAu moins un réseau en cours de publication
completedTous les réseaux ont réussi
partialAu moins un succès ET au moins un échec
failedTous les réseaux ont échoué
cancelledAnnulée avant publication

Par réseau : pending → publishing → succeeded ou failed (+ inbox_delivered pour un brouillon TikTok, cancelled quand la publication a été annulée avant son départ). TikTok est résolu en différé : la cible reste publishing jusqu'à confirmation réelle par TikTok (suivi automatique côté serveur), là où beaucoup d'outils annoncent « publié » dès l'acceptation de la demande.

Consulter et annuler

curl https://api.kreatoai.com/v1/posts/9f1c8b2e-... \
  -H "x-api-key: sk-kre-v1-votre_cle"

La réponse inclut, pour chaque réseau, l'identifiant du post publié (externalPostId), son lien (postUrl, quand le réseau l'expose) et en cas d'échec failReason + failType. DELETE /v1/posts/:id annule une publication programmée non partie (204) ; déjà partie → 409 post_not_cancellable. Si vous avez configuré un webhook, inutile de poller : un événement par réseau vous est envoyé.

Modifier une programmation

PATCH /v1/posts/:id change une publication programmée qui n'est pas encore partie. Envoyez seulement les champs à changer : scheduledAt pour la décaler, content, mediaUrls ou options. La publication garde son identifiant, et un nouveau texte ou de nouveaux médias sont vérifiés réseau par réseau comme à la création. Les comptes visés ne se modifient pas : pour en changer, annulez puis créez une nouvelle publication.

curl -X PATCH https://api.kreatoai.com/v1/posts/9f1c8b2e-... \
  -H "x-api-key: sk-kre-v1-votre_cle" \
  -H "Content-Type: application/json" \
  -d '{ "scheduledAt": "2026-09-18T08:23:00+01:00" }'

// 200 OK : la publication à jour, contenu et médias compris

Déjà partie, en cours d'envoi ou annulée → 409 post_not_editable. Date passée → 400 scheduled_at_in_past.

Réglages TikTok — brouillon ou publication directe

Par défaut, TikTok publie immédiatement et publiquement. Si vous préférez déposer le contenu dans les brouillons du créateur — qui relira puis publiera lui-même depuis l'app — passez options.tiktok.postMode à MEDIA_UPLOAD.

{
  "targets": ["tiktok"],
  "content": "Ma légende",
  "mediaUrls": ["https://media.kreatoai.com/1.jpg", "https://media.kreatoai.com/2.jpg"],
  "options": {
    "tiktok": {
      "postMode": "MEDIA_UPLOAD",          // brouillon ; défaut : DIRECT_POST
      "title": "Mon titre",                // photos : 90 caractères ; défaut : première ligne du texte
      "privacyLevel": "PUBLIC_TO_EVERYONE", // DIRECT_POST uniquement
      "disableComment": false,              // DIRECT_POST uniquement
      "disableDuet": false,                 // DIRECT_POST uniquement, vidéo
      "disableStitch": false,               // DIRECT_POST uniquement, vidéo
      "isAigc": false,                      // DIRECT_POST uniquement, vidéo générée par l'IA
      "autoAddMusic": true                  // DIRECT_POST uniquement, carrousel
    }
  }
}

En MEDIA_UPLOAD, confidentialité et interactions ne sont pas transmises : TikTok les fait choisir au créateur au moment où il publie. Les envoyer quand même n'a aucun effet.

En brouillonCarrousel d’imagesVidéo
Texte de la publicationTitre et description conservésNon transmis — saisi dans l’app
Limite TikTok—5 brouillons en attente / 24 h

Cette asymétrie vient de TikTok : un carrousel en brouillon passe par content/init, qui accepte un titre, tandis qu'une vidéo passe par inbox/video/init, qui n'accepte aucune métadonnée. Prévoyez donc de communiquer la légende autrement si vous déposez des vidéos en brouillon.

Le suivi ne change pas : la cible reste publishing jusqu'à confirmation réelle, puis passe à inbox_delivered pour un brouillon livré, ou succeeded pour une publication en ligne.

Story Facebook et Instagram

options.format à "story" publie une story au lieu d'une publication, sur une Page Facebook ou sur Instagram. Une story porte une seule image ou vidéo et aucun texte : content devient facultatif et n'est pas transmis. Elle reste visible 24 heures, puis la plateforme la retire.

{
  "targets": ["facebook", "instagram"],
  "mediaUrls": ["https://media.kreatoai.com/story.mp4"],
  "options": { "format": "story" }
}

Image en JPEG ou PNG ; vidéo en MP4, de 3 à 60 secondes, verticale (9:16) de préférence. Programmer une story fonctionne comme pour une publication, avec scheduledAt.

Idempotence — évitez les doubles publications

Si votre workflow réessaie après un timeout réseau, le même appel peut partir deux fois — et sans protection, publier deux fois. Fournissez un idempotencyKey stable (par exemple l'identifiant de votre tâche interne) : si une publication existe déjà avec cette clé, l'API renvoie la publication existante (200) au lieu d'en créer une seconde. Recommandé pour toute intégration automatisée.

Validation et erreurs

Tout est vérifié avant d'accepter la requête — échec rapide avec le détail par réseau, plutôt qu'un échec silencieux trente secondes plus tard :

// 400 Bad Request
{
  "error": "invalid_targets",
  "message": "Certains réseaux ne peuvent pas recevoir cette publication.",
  "details": [
    { "platform": "instagram", "error": "media_required_for_target" },
    { "platform": "tiktok", "error": "channel_not_connected" }
  ]
}
CodeCause
invalid_targetRéseau inconnu (valides : facebook, instagram, linkedin, tiktok, youtube, bluesky, google_business)
video_required_for_targetYouTube ne publie que des vidéos (Shorts) : ni texte seul, ni image. Première ligne du texte = titre (100 car.), texte entier = description ; options.youtube.privacyStatus (public par défaut), madeForKids, title, tags (500 car. cumulés), containsSyntheticMedia (déclaration de contenu IA réaliste)
duplicate_targetLe même compte est visé deux fois (deux comptes distincts d’un même réseau sont valides)
channel_not_connectedAucun canal actif pour ce réseau, ou channelId inconnu de votre espace
content_too_long_for_targetTexte au-delà de la limite du réseau (LinkedIn 3 000, Instagram/TikTok 2 200, Google Business 1 500, Bluesky 300)
media_required_for_targetInstagram et TikTok exigent au moins un média
document_linkedin_onlyUn PDF ne part que sur LinkedIn, en carrousel document
video_unsupported_targetGoogle Business ne publie pas de vidéo
too_many_media_for_targetBluesky accepte 4 images ou une vidéo seule, Google Business une image
document_aloneUn PDF part seul : aucun autre média dans mediaUrls
story_unsupported_targetUne story ne part que sur facebook ou instagram
story_single_mediaUne story porte une seule image ou vidéo
content_requiredTexte vide : il est obligatoire, sauf pour une story
scheduled_at_in_pastDate de programmation déjà passée
media_unreadableMédia inaccessible ou type indéterminable

En cas d'échec de publication, failType distingue retriable (indisponibilité passagère, limite de débit — réessayer plus tard peut réussir) et permanent (média refusé, canal à reconnecter — réessayer est inutile). Ne bouclez jamais sur un échec permanent.

Limites actuelles

Facebook publie plusieurs photos en une seule publication, Bluesky jusqu'à quatre (ou une vidéo MP4 seule), Google Business une seule (jamais de vidéo, et un bouton facultatif dans options.google_business.callToAction). Instagram, TikTok et LinkedIn publient toutes les images en carrousel, de 2 à 10 ; sur LinkedIn le carrousel est un document PDF assemblé côté serveur, une page carrée par image. Une vidéo part en Reel sur Instagram, ou en story avec options.format. La visibilité d'une publication LinkedIn n'est pas encore réglable.