API & développeurs
Selamia pour les développeurs et les agents IA
Une API REST claire, des webhooks pour tous les événements et un serveur MCP : programme des posts depuis ton site, ton CRM ou ta caisse, envoie chaque nouvel avis Google dans Slack, ou laisse Claude préparer ta semaine. Inclus dans les offres Pro, Pilote et Agence.
Inclus dans les offres Pro, Pilote et Agence (et pendant l'essai gratuit).
Vue d'ensemble
API REST v1
JSON, dates ISO, pagination par curseur, création idempotente, messages d'erreur en français prêts à afficher.
Webhooks pour tout
14 événements signés HMAC-SHA256, relances automatiques, journal des envois et test en un clic.
Serveur MCP
8 outils pour Claude, Cursor et tout client MCP — avec les temps forts français et ton Brand Kit.
Ce que Selamia fait mieux
- Des webhooks pour tous les événements, pas seulement la publication
- Les mêmes règles que l'appli : limites des réseaux, quotas, validation client
- Idempotency-Key : un nouvel essai ne crée jamais de doublon
- Import de médias par URL sécurisé (aucun réseau privé, taille et type vérifiés)
- Une clé par espace et par outil : pensé pour les agences
- Messages d'erreur en français, prêts à montrer à tes clients
Authentification
Crée une clé dans Paramètres › Développeurs (propriétaire ou admin). Envoie-la dans l'en-tête Authorization de chaque requête. Une clé appartient à un espace et agit avec le rôle actuel de la personne qui l'a créée : si elle quitte l'équipe, la clé cesse de fonctionner. Seule une empreinte SHA-256 est conservée : la clé n'est montrée qu'une fois.
GET /api/v1/me HTTP/1.1
Host: selamia.com
Authorization: Bearer pk_live_…| Droits (scopes) | Description |
|---|---|
| posts:read | Lire les posts |
| posts:write | Créer et programmer des posts |
| accounts:read | Voir les réseaux connectés |
| media:write | Envoyer des médias |
| stats:read | Lire les statistiques |
| ai:write | Utiliser l'IA |
Démarrage rapide
Trois appels pour programmer ton premier post. scheduledAt accepte une date ISO 8601 avec fuseau, "next_slot" (prochain créneau libre de la file) ou "now". Sans scheduledAt, le post reste en brouillon.
export SELAMIA_KEY="pk_live_…"
# 1. Ton espace, tes droits et ta consommation
curl https://selamia.com/api/v1/me -H "Authorization: Bearer $SELAMIA_KEY"
# 2. Tes réseaux connectés (identifiants)
curl https://selamia.com/api/v1/accounts -H "Authorization: Bearer $SELAMIA_KEY"
# 3. Programmer un post au prochain créneau libre
curl -X POST https://selamia.com/api/v1/posts \
-H "Authorization: Bearer $SELAMIA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: menu-de-saison-2026" \
-d '{
"caption": "Le menu de saison arrive mardi 🍂",
"hashtags": ["lyon", "bistrot"],
"accountIds": ["<instagram-id>", "<facebook-id>"],
"mediaUrls": ["https://example.com/photos/menu.jpg"],
"scheduledAt": "next_slot",
"overrides": {
"<facebook-id>": { "caption": "Version Facebook : réserve ta table !" }
}
}'{
"object": "post",
"id": "21eef5cd-043d-4c21-aa56-9d873a29c2c2",
"status": "scheduled",
"format": "image",
"caption": "Le menu de saison arrive mardi 🍂",
"scheduledAt": "2026-10-20T10:30:00.000Z",
"targets": [
{ "network": "Instagram", "status": "scheduled", "permalink": null, "error": null },
{ "network": "Facebook", "status": "scheduled", "permalink": null, "error": null }
],
"url": "https://selamia.com/app/posts/21eef5cd-…"
}Endpoints
Adresse de base : https://selamia.com/api/v1
| Méthode | Chemin | Scope | Description |
|---|---|---|---|
| GET | /me | — | Espace, clé, rôle, offre et consommation du mois |
| GET | /accounts | accounts:read | Réseaux connectés (formats, limites) |
| GET | /posts?from&to&status&accountId&cursor | posts:read | Posts triés par date, pagination par curseur |
| GET | /posts/:id | posts:read | Un post et son statut par réseau |
| POST | /posts | posts:write | Brouillon, programmation, publication immédiate ou file |
| PATCH | /posts/:id | posts:write | Modification partielle, (re)programmation |
| DELETE | /posts/:id | posts:write | Suppression (publications prévues annulées) |
| POST | /posts/:id/retry | posts:write | Relance des publications en échec |
| POST | /media | media:write | Fichier (multipart) ou import d'URL sécurisé |
| GET | /slots/next?accountIds&count | posts:read | Prochains créneaux libres de la file |
| GET | /stats/summary?period=30d | stats:read | Chiffres clés, meilleurs posts, recommandations |
| POST | /ai/caption | ai:write | Légendes IA dans le ton de la marque (1 crédit) |
| GET | /brand-kit | — | Identité de la marque (couleurs, ton, contact) |
| GET | /moments?days=45 | — | Temps forts français à venir + idées de posts |
Schémas complets : openapi.json (à importer dans Postman, Insomnia ou ton générateur de code).
Webhooks
Ajoute une adresse HTTPS dans Paramètres › Développeurs, choisis les événements : Selamia envoie un POST signé pour chacun. Réponds par un code 2xx en moins de 10 secondes ; sinon on réessaie après 1 min, 5 min, 30 min, 2 h et 12 h. Après 20 échecs d'affilée, le webhook est mis en pause et le propriétaire prévenu. Utilise l'id de l'événement pour dédoublonner.
Événements
post.createdUn nouveau post (brouillon compris) est créé.post.updatedLe texte, les médias, les réseaux ou la date d'un post changent.post.scheduledUn post est programmé (ou reprogrammé) pour une date.post.approval_requestedUn post est envoyé en validation (client ou responsable).post.approvedLe client ou le responsable valide un post.post.changes_requestedLe client ou le responsable demande des modifications.post.publishedUn post est en ligne sur un réseau (un envoi par réseau, avec le lien).post.failedUne publication a échoué définitivement sur un réseau (raison en français).post.deletedUn post est supprimé (ses publications prévues sont annulées).comment.receivedUn nouveau commentaire arrive dans la boîte de réception.review.receivedUn nouvel avis Google arrive (avec sa note).account.connectedUn compte social est connecté (ou reconnecté).account.expiredLa connexion d'un compte a expiré : il faut le reconnecter.report.readyLe rapport PDF mensuel est généré.
Contenu envoyé
{
"id": "evt_9mQ2xK…",
"type": "post.published",
"createdAt": "2026-10-20T10:30:04.512Z",
"workspaceId": "d4328…",
"data": {
"post": { "id": "21eef5cd-…", "status": "published", "caption": "…", "targets": [ … ] },
"target": {
"network": "Instagram",
"status": "published",
"permalink": "https://www.instagram.com/p/…",
"publishedAt": "2026-10-20T10:30:03.981Z"
}
}
}En-têtes : Selamia-Signature (t=horodatage,v1=HMAC-SHA256 de « t.corpsBrut » avec ton secret whsec_), Selamia-Event, Selamia-Event-Id, Selamia-Delivery.
Vérifier la signature (Node.js)
import crypto from "node:crypto";
import express from "express";
const app = express();
const SECRET = process.env.SELAMIA_WEBHOOK_SECRET; // whsec_…
// Garde le corps brut : la signature porte sur les octets exacts
app.post("/webhooks/selamia", express.raw({ type: "application/json" }), (req, res) => {
const header = req.get("Selamia-Signature") ?? "";
const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const expected = crypto.createHmac("sha256", SECRET).update(`${t}.${req.body}`).digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300; // anti-rejeu : 5 min
const valid = !!v1 && v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
if (!fresh || !valid) return res.status(400).send("Invalid signature");
const event = JSON.parse(req.body);
// Dédoublonne avec event.id, réponds vite, traite en arrière-plan
if (event.type === "review.received") notifySlack(event.data.item);
res.sendStatus(200);
});
app.listen(3001);Serveur MCP pour les agents IA
Selamia parle le Model Context Protocol (Streamable HTTP) à l'adresse https://selamia.com/api/mcp, avec les mêmes clés, droits et règles que l'API. Branche-le à Claude Code, Claude Desktop, Cursor ou tout client MCP, puis demande : « Prépare 3 posts pour Halloween et programme-les sur Instagram et Facebook aux meilleurs moments. »
claude mcp add --transport http selamia https://selamia.com/api/mcp \
--header "Authorization: Bearer pk_live_…"{
"mcpServers": {
"selamia": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://selamia.com/api/mcp",
"--header",
"Authorization:${SELAMIA_AUTH}"
],
"env": {
"SELAMIA_AUTH": "Bearer pk_live_…"
}
}
}
}{
"mcpServers": {
"selamia": {
"url": "https://selamia.com/api/mcp",
"headers": {
"Authorization": "Bearer pk_live_…"
}
}
}
}Outils
list_accountsVoir les réseaux connectés
list_postsLire le calendrier (filtres date / statut)
create_postCréer un brouillon ou programmer un post
schedule_postProgrammer un brouillon existant
generate_captionRédiger une légende dans le ton de la marque
get_stats_summaryRésumé des statistiques de la période
list_upcoming_momentsTemps forts français à venir + idées
get_brand_kitIdentité de la marque (couleurs, ton, contact)
L'agent a exactement les droits de la clé : sans posts:write, il ne peut pas créer de post. Brouillons par défaut, publication seulement sur demande.
Limites et erreurs
120 requêtes par minute et par clé (REST + MCP). Chaque réponse porte X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset ; une 429 porte aussi Retry-After. Les erreurs ont toujours la forme { "error": { "code", "message", "details"? } } : code est stable (anglais), message est en français, prêt à afficher.
{
"error": {
"code": "unprocessable",
"message": "Impossible de programmer :\n• Instagram demande au moins une image ou une vidéo.",
"details": ["Instagram demande au moins une image ou une vidéo."]
}
}| HTTP | code | Description |
|---|---|---|
| 401 | unauthorized / invalid_api_key | Clé absente, invalide ou révoquée |
| 403 | insufficient_scope / forbidden | Droit manquant sur la clé ou rôle insuffisant |
| 403 | plan_required | Offre sans plateforme développeurs |
| 400 | validation_error / invalid_json | Corps ou paramètres invalides (détails par champ) |
| 404 | not_found | Ressource absente de cet espace |
| 402 | limit_reached | Quota de l'offre atteint (posts, crédits IA, stockage) |
| 422 | unprocessable | Contenu refusé (règle d'un réseau, validation client…) |
| 429 | rate_limited | Plus de 120 requêtes / minute |
- Dates en UTC (ISO 8601) ; le fuseau de l'espace est donné par GET /me.
- Idempotency-Key sur POST /posts : un nouvel essai renvoie le même post.
- Pagination : passe nextCursor en ?cursor= tant que hasMore vaut true.
Construis sur Selamia dès aujourd'hui
Choisis un modèle ou écris ton idée à Selamia IA : ton premier post peut être prêt en quelques minutes.
Gratuit, sans limite de temps Sans carte bancaire Pilote offert 14 jours



