UGCPocket docs

API REST & serveur MCP

UGC Pocket expose une couche de commande pour agents : estimer puis commander une campagne UGC en REST ou en MCP, et, côté créateur, déclarer des vidéos publiées. Une commande d'agent crée toujours une campagne au statut draft ; un humain la confirme et la finance dans l'app. Aucun paiement n'est déclenché par un agent.

Vue d'ensemble

Base RESThttps://ugcpocket.com/api
Serveur MCPhttps://ugcpocket.com/mcp · Streamable HTTP, protocole 2025-06-18
Spécification/openapi.json (OpenAPI 3.1)
DeviseEUR, montants en centimes
Budget campagne300 000 à 10 000 000 centimes (2 000 € à 100 000 €)

Le brouillon créé par un agent est rattaché à l'organisation propriétaire de la clé. La réponse contient un confirm_url qui ouvre la campagne dans l'app pour confirmation et financement. budget_max_cents est le forfait de campagne, facturé en totalité : UGC Pocket briefe, sélectionne et rémunère les créateurs, et s'engage à en tirer le maximum de vues.

Démarrage

Un agent ne s'inscrit pas seul : l'accès est amorcé par un humain dans l'app.

  1. Télécharger l'app UGC Pocket, puis créer un compte organisation (côté marque) ou créateur. Un agent ne peut pas s'inscrire seul.
  2. Générer une clé : marques dans Profil → « Clés API/MCP », créateurs dans Réglages → « Clés API/MCP ». La clé ugcp_live_… n'est affichée qu'une fois.
  3. Configurer l'agent avec l'en-tête Authorization: Bearer ugcp_live_….

Première requête

curl -X POST https://ugcpocket.com/api/campaigns \
  -H "Authorization: Bearer ugcp_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "title": "Lancement gamelle",
    "brief": "Vidéo TikTok mettant en scène le produit…",
    "prestation": "video_post",
    "target_categories": ["dog"],
    "platforms": ["TikTok"],
    "budget_max_cents": 350000
  }'
HTTP/1.1 201 Created
{
  "campaign_id": "8b1f…",
  "status": "draft",
  "ordered_by_agent": true,
  "next_step": "La marque doit confirmer et financer la campagne dans l'app UGC Pocket.",
  "confirm_url": "https://ugcpocket.com/c/8b1f…"
}

Authentification

Clé API au format ugcp_live_…, transmise dans l'en-tête Authorization: Bearer. Une clé porte un scope qui détermine les surfaces accessibles.

ScopeGénéré parDonne accès à
campaigns:draftCompte organisation (marque)POST /campaigns, GET /campaigns/{id}, et les 3 outils MCP marque.
creator:submitCompte créateurLes 3 outils MCP créateur : campagnes acceptées, dépôt de vidéo publiée, livrables.

Une clé au mauvais scope reçoit insufficient_scope (403) en REST, et un rejet métier en MCP. Une clé se révoque dans l'app, au même endroit que sa création : elle répond ensuite key_revoked (401). Une clé expirée répond key_expired (401).

Sans clé. Deux endpoints REST sont ouverts (GET /service-info, POST /estimate), ainsi que la découverte MCP (initialize, tools/list) et l'outil get_service_info. Tout le reste exige une clé. Attention à l'asymétrie : POST /estimate est public en REST, mais l'outil MCP estimate_campaign demande une clé campaigns:draft.

API REST

Base https://ugcpocket.com/api. Les réponses sont en JSON ; les erreurs suivent l'enveloppe { "error": "code", "detail": "…" }. Les routes à clé n'émettent pas d'en-têtes CORS : elles sont faites pour un appel serveur à serveur, pas depuis un navigateur.

EndpointAuthRôle
GET/service-infoaucuneDescripteur produit : énumérations, plancher de budget, liens.
POST/estimateaucuneBrief libre → champs suggérés + estimation.
POST/campaignscampaigns:draftCrée un brouillon de campagne.
GET/campaigns/{id}clé APIStatut d'une campagne de l'organisation.
GET/api/service-info

Descripteur du service, sans authentification. Retourne les valeurs valides des énumérations (categories, prestations, platforms), currency, budget_unit, min_campaign_budget_cents, le modèle de commande, et les liens vers openapi.json, mcp et cette documentation. À appeler en premier : c'est la source de vérité des énumérations. GET / renvoie la même charge utile.

POST/api/estimate

Analyse un brief en texte libre (français ou anglais) et retourne des champs structurés plus une estimation de ce que le plafond peut produire. N'écrit rien en base.

// Requête
{ "brief": "Des vidéos UGC pour nos croquettes, cible maîtres de chiens, budget max 5 000 €" }

// 200 OK
{
  "suggested": { "title": "…", "prestation": "video_post", "target_categories": ["dog"],
                 "platforms": ["TikTok"], "budget_max_cents": 500000 },
  "estimate": { "budget_max_cents": 500000, "estimated_creators": 33,
                "estimated_videos": 165, "max_views": 3750000, "note": "…" }
}

estimate vaut null si aucun budget ne peut être déduit du brief. brief manquant ou non textuel → validation_error (422).

POST/api/campaigns

Crée une campagne au statut draft. Corps : un objet CampaignDraftInput. Exige une clé au scope campaigns:draft. Réponse 201 avec campaign_id, status, ordered_by_agent, next_step, confirm_url.

En-tête Idempotency-Key optionnel : la réponse est mise en cache 24 h par clé, rejouer la même requête renvoie le même campaign_id au lieu de créer un doublon. Utilisez un UUID par intention de commande, pas par tentative.

GET/api/campaigns/{id}

Retourne campaign_id, title, status, ordered_by_agent et confirm_url. La recherche est limitée aux campagnes de l'organisation propriétaire de la clé : un identifiant appartenant à une autre organisation renvoie not_found (404), pas 403.

Statuts possibles : draft, open, in_progress, completed, cancelled.

CampaignDraftInput

Objet envoyé à POST /campaigns et à l'outil MCP create_campaign_order. Schéma complet dans /openapi.json.

L'entrée est normalisée, pas refusée strictement. Deux choses seulement renvoient une erreur : un champ requis manquant, et budget_max_cents sous le plancher. Le reste est corrigé en silence, donc lisez la réponse plutôt que de supposer que votre charge utile est passée telle quelle : title et brief sont tronqués à leur longueur maximale, les valeurs d'énumération inconnues sont retirées de target_categories et platforms, un prestation invalide retombe sur video_post, objectives ne garde que ses 6 premières entrées, un budget au-dessus du plafond est ramené à 10000000, et les champs non déclarés sont ignorés.

ChampTypeDétail
titlerequisstring ≤ 120Titre court de la campagne.
briefrequisstring ≤ 2000Consignes créatives, ton, contraintes.
budget_max_centsrequisintegerCentimes d'euro. 200000 minimum (2 000 €), en dessous c'est un 422. Au-dessus de 10000000 (100 000 €) la valeur est ramenée au plafond, pas refusée. Forfait de campagne, facturé en totalité.
prestationenumvideo_post (défaut et seule valeur).
target_categoriesenum[]Voir les 22 catégories ci-dessous.
platformsenum[]TikTok, Instagram, YouTube, Snapchat, Facebook.
objectivesstring[]Objectifs libres de la campagne.
brief_rawstringBrief d'origine non retouché, conservé tel quel.
payment_triggerenumpublication ou views.
views_thresholdinteger ≥ 0Seuil de vues, si payment_trigger=views.
deadlinedate ISOAAAA-MM-JJ.

Catégories

dogcatpetscarcookingcouplefamilykidsbusinessfinancepodcastsportwellnessbeautyfashiontechgaminghomegardendiytravellifestyle

Ces valeurs sont celles acceptées par l'API. Appelez GET /service-info plutôt que de les figer dans votre code.

Erreurs

Toutes les erreurs REST utilisent l'enveloppe { "error", "detail" }. Le champ error est stable, detail est un message lisible qui peut changer.

HTTPerrorCause
401invalid_api_keyClé absente, inconnue ou mal formée.
401key_revokedClé révoquée dans l'app.
401key_expiredClé arrivée à expiration.
403insufficient_scopeLa clé ne porte pas campaigns:draft.
404not_foundCampagne inexistante, hors de l'organisation, ou route inconnue.
422validation_errortitle manquant, brief non textuel, ou budget_max_cents absent, non numérique ou inférieur à 200000. Les énumérations inconnues et les champs non déclarés n'arrivent pas ici : ils sont retirés en silence.
429rate_limitedDébit dépassé. En-tête Retry-After: 60.
400create_failedRefus à l'écriture en base : plafond de 200 brouillons sur 24 h atteint, ou clé non autorisée pour l'organisation. Le motif est dans detail.
500internalErreur serveur. Rejouable avec la même Idempotency-Key.

Limites

LimiteValeurComportement au dépassement
Débit par clé30 requêtes / minute429 rate_limited + Retry-After: 60
Brouillons par clé200 par fenêtre de 24 h glissante400 create_failed, detail = « daily draft cap reached »
Budget de campagne300 000 – 10 000 000 centimesSous le plancher : 422 validation_error. Au-dessus du plafond : ramené à 10 000 000.
Cache d'idempotence24 h par cléAu-delà, la même clé d'idempotence recrée une campagne

Serveur MCP

Serveur MCP Streamable HTTP sur https://ugcpocket.com/mcp, protocole 2025-06-18, ugc-pocket-mcp v1.2.0. Transport JSON uniquement : le serveur n'émet pas de flux SSE, et un client qui n'accepte pas application/json reçoit 406. Seul POST est accepté.

La découverte (initialize, tools/list) et l'outil get_service_info fonctionnent sans clé. Les six autres outils exigent la clé en en-tête.

Configuration client

{
  "mcpServers": {
    "ugc-pocket": {
      "type": "http",
      "url": "https://ugcpocket.com/mcp",
      "headers": { "Authorization": "Bearer ugcp_live_VOTRE_CLE" }
    }
  }
}
Limite côté client. Les connecteurs MCP de claude.ai grand public n'acceptent à ce jour que l'authentification OAuth, pas une clé bearer. Le serveur MCP s'utilise donc depuis les clients à en-têtes personnalisés (Claude Code, Cursor, etc.). L'API REST reste utilisable partout. Un connecteur OAuth est une itération future.

Outils marque campaigns:draft

OutilEntréeRôle
get_service_info
sans clé
aucuneDescripteur produit et énumérations valides. Lecture seule, idempotent.
estimate_campaignbrief requisBrief libre → champs structurés + estimation (créateurs, vidéos, vues maximales). N'écrit rien.
create_campaign_orderCampaignDraftInputCrée un brouillon. Accepte l'en-tête HTTP Idempotency-Key, comme en REST.
check_campaign_statuscampaign_id requisStatut d'une campagne de l'organisation.

Outils créateur creator:submit

Pensés pour les créateurs qui déclarent beaucoup de vidéos publiées, par exemple plusieurs centaines sur un challenge. Clé générée côté créateur dans Réglages → « Clés API/MCP ».

OutilEntréeRôle
list_my_campaignsaucuneCampagnes sur lesquelles vous êtes retenu : campaign_id, titre, statut, prestation, déclencheur de paiement, rémunération, échéance, brief.
submit_posted_videocampaign_id, video_url requisDéclare une vidéo publiée. URL TikTok, Instagram ou YouTube : suivi de vues quotidien pendant 1 mois. Autre URL https : stockée sans suivi. Idempotent par couple campagne + URL, already_submitted signale le rejeu. 30 requêtes/min.
list_my_deliverablescampaign_id, before (optionnels)Vos vidéos et leur état (submitted, published, validated, revision, paid), vues suivies, montants validés en centimes. 200 par appel, pagination en passant le plus ancien created_at dans before.

Erreurs JSON-RPC

Deux registres distincts, à ne pas confondre côté agent : une erreur de protocole est un objet error, un refus métier est un result avec isError: true et un message exploitable.

CodeCause
-32001Clé absente ou invalide. HTTP 401 + WWW-Authenticate: Bearer.
-32601Outil ou méthode inconnue.
-32602Argument requis manquant.
-32700 / -32600JSON illisible / requête JSON-RPC invalide.
-32603Erreur interne.
isError: trueRefus métier : mauvais scope, budget hors bornes, campagne introuvable, plafond quotidien.

Ressources machine

RessourceRôle
/openapi.jsonSpécification OpenAPI 3.1 de l'API REST.
/llms.txtDécouverte et contexte produit lisibles par un LLM.
/llms-full.txtVersion étendue.

Question d'intégration : hello@logics-studio.com