Publica y programa en 13 redes con una sola API REST. Lee analíticas, responde comentarios y DMs y recibe un webhook firmado en cuanto una publicación sale, falla o se aprueba.
Authorization: Bearer YOUR_API_KEY {"content":"Our autumn menu lands on Friday.","social_profile_ids":[101,102],"publish_time":"2026-11-13T09:00","timezone":"America/New_York","status":"scheduled"}
{"id":18342,"status":"scheduled","publish_time":"2026-11-13T09:00:00-05:00","timezone":"America/New_York","social_profiles":[{"name":"Northwind Instagram","platform":"instagram","status":"pending"},{"name":"Northwind LinkedIn","platform":"linkedin","status":"pending"}]}
X-RobinReach-Event: post.published X-RobinReach-Signature: t=1794150000,v1=5257a869e7… {"id":"evt_1c626cf6bcb5","type":"post.published","data":{"post":{"id":18342,"status":"published","summary":{"total":2,"published":2,"failed":0}}}}
Un intercambio de ejemplo con IDs inventados. Los webhooks llegan como un POST firmado a tu endpoint HTTPS.
Envía el texto, los perfiles y la hora. RobinReach comprueba la publicación con las reglas de cada red, la pone en el calendario y la publica a tiempo.
GET /api/v1/social_profiles para obtener los IDs de las cuentas en las que quieres publicar.timezone que indiques, así que 09:00 son las 9:00 para tu audiencia.¿No sabes si una publicación pasará? POST /api/v1/posts/validate hace las mismas comprobaciones sin guardar nada.
curl -X POST https://robinreach.com/api/v1/posts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "Our autumn menu lands on Friday.", "social_profile_ids": [ 101, 102 ], "publish_time": "2026-11-13T09:00", "timezone": "America/New_York", "status": "scheduled" }'
require "net/http" require "json" uri = URI("https://robinreach.com/api/v1/posts") request = Net::HTTP::Post.new(uri, "Authorization" => "Bearer YOUR_API_KEY", "Content-Type" => "application/json") request.body = { content: "Our autumn menu lands on Friday.", social_profile_ids: [101, 102], publish_time: "2026-11-13T09:00", timezone: "America/New_York", status: "scheduled" }.to_json response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(request) } puts response.body
const response = await fetch("https://robinreach.com/api/v1/posts", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ content: "Our autumn menu lands on Friday.", social_profile_ids: [101, 102], publish_time: "2026-11-13T09:00", timezone: "America/New_York", status: "scheduled", }), }); console.log(await response.json());
import requests response = requests.post( "https://robinreach.com/api/v1/posts", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "content": "Our autumn menu lands on Friday.", "social_profile_ids": [101, 102], "publish_time": "2026-11-13T09:00", "timezone": "America/New_York", "status": "scheduled", }, timeout=30, ) print(response.json())
La API cubre el trabajo que tu equipo hace en el panel, para que tu código también pueda hacerlo.
Crea, valida, publica ya, reprograma y elimina publicaciones, con las opciones propias de cada red.
/posts/posts/validate/posts/{id}/posts/{id}/publish_now/posts/{id}/rescheduleSube imágenes, vídeos y PDF, ordénalos en carpetas y reutilízalos en tus publicaciones.
/attachments/attachments/{id}/folders/folders/{id}Lista las marcas y los perfiles conectados, además de tableros de Pinterest, audio de Instagram, categorías y etiquetas de WordPress, ubicaciones y grupos de hashtags.
/brands/brands/{id}/social_profiles/social_profiles/{id}/social_profiles/{id}/pinterest_boards/locations/hashtag_groupsLa interacción por perfil y por publicación, tus mejores publicaciones, esta semana frente a la anterior y el calendario.
/analytics/summary/analytics/top_posts/posts/{id}/analytics/social_profiles/{id}/analytics/calendarLee los hilos de comentarios, los DMs de Facebook e Instagram y las reseñas de Google de tus perfiles, y responde como la marca.
/comment_threads/comment_threads/{id}/replyCrea, pausa y reanuda automatizaciones de Comment to DM, feeds RSS y tareas de reutilización. Comprueba un feed antes de añadirlo y ejecuta una tarea cuando quieras.
/comment_automations/comment_automations/{id}/pause/rss_feeds/rss_feeds/validate/rss_feeds/{id}/sync/repurposing_tasks/repurposing_tasks/{id}/runEdita la página bio de la marca y sus bloques, ordénalos, consulta las analíticas de la página y obtén su código QR.
/bio_page/bio_page/blocks/bio_page/blocks/{id}/bio_page/blocks/reorder/bio_page/analytics/bio_page/qrCon los Connect Links los clientes añaden sus propias cuentas. Con los Approval Links revisan publicaciones sin iniciar sesión.
/connect_links/connect_links/{id}/approval_links/approval_links/{id}Añade endpoints, envía eventos de prueba, rota los secretos de firma y consulta el registro de entregas.
/webhook_endpoints/webhook_endpoints/{id}/webhook_endpoints/{id}/test/webhook_endpoints/{id}/rotate_secret/webhook_endpoints/{id}/enable/webhook_endpoints/{id}/deliveriesAñade un endpoint HTTPS y RobinReach envía un POST firmado para los eventos que elijas. Avisa a tu equipo, sincroniza tu CRM o responde un comentario o un DM en el segundo en que llega.
post.publishedUna publicación salió en todos los perfiles seleccionados.post.partially_publishedUna publicación salió en algunos perfiles y falló en otros.post.failedUna publicación falló en todos los perfiles seleccionados, con el motivo de cada uno.post.approvedUna publicación se aprobó en el panel o mediante un Approval Link.post.rejectedUna publicación se rechazó, con la nota de quien la revisó.comment.receivedOtra persona comentó en un perfil conectado. Tus propias respuestas nunca lo activan.review.receivedLlegó una reseña nueva al Perfil de Empresa de Google.message.receivedAlguien envió un mensaje directo a una página de Facebook o una cuenta de Instagram conectada.Hasta 10 endpoints por marca. Con la clave maestra, un endpoint en tu marca predeterminada puede escuchar todas las marcas a la vez.
{
"id": "evt_1c626cf6bcb54613a8053e24d5361527",
"type": "post.published",
"created_at": "2026-11-13T14:00:00Z",
"api_version": "2026-11-01",
"data": {
"brand": {
"id": "northwind",
"name": "Northwind Coffee"
},
"post": {
"id": 18342,
"status": "published",
"content": "Our autumn menu lands on Friday.",
"social_profiles": [
{
"id": 101,
"platform": "instagram",
"status": "published",
"remote_url": "https://www.instagram.com/p/C9xYz12AbCd/"
},
{
"id": 102,
"platform": "linkedin",
"status": "published",
"remote_url": "https://www.linkedin.com/feed/update/urn:li:share:7392018841650188288/"
}
],
"summary": {
"total": 2,
"published": 2,
"failed": 0
}
}
}
}
Cada petición lleva X-RobinReach-Signature: t=…,v1=…, un HMAC-SHA256 de la marca de tiempo y el cuerpo sin procesar, firmado con el secreto de tu endpoint. Compruébalo antes de fiarte del contenido y rechaza marcas de tiempo de más de cinco minutos.
class RobinreachWebhooksController < ActionController::API def create body = request.raw_post return head :unauthorized unless valid_signature?(body, request.headers["X-RobinReach-Signature"]) event = JSON.parse(body) # Skip event["id"] if you have seen it, then queue the work. head :ok end private def valid_signature?(body, header, tolerance: 300) parts = header.to_s.split(",").map { |p| p.split("=", 2) }.select { |kv| kv.size == 2 }.to_h t = Integer(parts["t"].to_s, exception: false) return false unless t && parts["v1"] && (Time.now.to_i - t).abs <= tolerance expected = OpenSSL::HMAC.hexdigest("SHA256", ENV.fetch("ROBINREACH_WEBHOOK_SECRET"), "#{t}.#{body}") ActiveSupport::SecurityUtils.secure_compare(expected, parts["v1"]) end end
import crypto from "node:crypto"; import express from "express"; const app = express(); app.post("/webhooks/robinreach", express.raw({ type: "application/json" }), (req, res) => { const raw = req.body.toString("utf8"); if (!verify(raw, req.get("X-RobinReach-Signature"), process.env.ROBINREACH_WEBHOOK_SECRET)) { return res.sendStatus(401); } const event = JSON.parse(raw); // Skip event.id if you have seen it, then queue the work. res.sendStatus(200); }); function verify(rawBody, header, secret, toleranceSec = 300) { const parts = Object.fromEntries((header || "").split(",").map((p) => p.split("=", 2))); const t = Number(parts.t); if (!t || !parts.v1 || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false; const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex"); const a = Buffer.from(expected), b = Buffer.from(parts.v1); return a.length === b.length && crypto.timingSafeEqual(a, b); }
import hashlib, hmac, os, time from flask import Flask, request, abort app = Flask(__name__) @app.post("/webhooks/robinreach") def robinreach_webhook(): raw = request.get_data() if not verify(raw, request.headers.get("X-RobinReach-Signature", ""), os.environ["ROBINREACH_WEBHOOK_SECRET"]): abort(401) event = request.get_json() # Skip event["id"] if you have seen it, then queue the work. return "", 200 def verify(raw_body, header, secret, tolerance=300): parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p) try: t = int(parts["t"]) except (KeyError, ValueError): return False if "v1" not in parts or abs(time.time() - t) > tolerance: return False expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, parts["v1"])
Una entrega fallida se reintenta 7 veces durante unas 28 horas, con intervalos cada vez más largos.
Tras 10 entregas fallidas seguidas, el endpoint se pausa y el administrador de la marca recibe un email. Reanúdalo con un clic.
Cada evento tiene un ID único, para que tu código pueda ignorar el raro duplicado.
Cada intento, código de estado y cuerpo de respuesta se guarda 30 días, y puedes enviar un evento de prueba cuando quieras.
https://robinreach.com/api/v1. Todas las rutas de esta página son relativas a ella.Authorization: Bearer YOUR_API_KEY. Un parámetro api_key en la URL también funciona, pero puede acabar en los registros del servidor, así que mejor usa la cabecera.brand_id. Una clave de marca solo llega a una marca, así que puedes dársela sin riesgo a un cliente o a una herramienta con un solo uso.America/New_York, o en la de la marca si no indicas ninguna.401 si falta la clave o es incorrecta, 404 para todo lo que queda fuera del alcance de la clave, 422 con un mensaje claro cuando una publicación incumple las reglas de una red.429 con las cabeceras Retry-After y X-RateLimit-*, para que tu cliente pueda frenar por sí solo./api/v1, y cada webhook indica la versión de su contenido en api_version.Cada red conserva sus propias opciones, como los Reels de Instagram, los títulos de YouTube, los tableros de Pinterest o las publicaciones de documento de LinkedIn, definidas por publicación en platform_options.
Dales a tus usuarios publicación en 13 redes sin construir ni mantener tú la API de cada red.
Gestiona cada marca cliente desde una cuenta, con una clave de marca y sus propios webhooks para cada cliente.
Convierte productos, anuncios, artículos o eventos nuevos en publicaciones programadas en cuanto existen.
Envía las publicaciones fallidas a Slack, lleva los resultados a tu CRM y trae las analíticas a tus propios paneles.
Claude, ChatGPT, Cursor y tus propios agentes obtienen las mismas acciones como herramientas, con una URL y la misma clave.
Ver el servidor MCPInstala n8n-nodes-robinreach y programa publicaciones desde cualquier flujo de n8n.
Ver en GitHubLlama a la API desde un paso de webhook en Zapier o un módulo HTTP en Make. La página Integraciones tiene los ajustes listos para copiar.
Abrir IntegracionesAuthorization: Bearer YOUR_API_KEY. Un parámetro api_key en la URL también funciona, pero la cabecera mantiene la clave fuera de los registros del servidor.brand_id. Cada marca puede tener además su propia clave de marca, que solo funciona en esa marca: no necesita brand_id, no ve tus otras marcas y no puede crear ni eliminar marcas.POST /api/v1/posts con el content, los social_profile_ids, un publish_time en ISO 8601, un timezone como America/New_York y status en scheduled. Llama antes a POST /api/v1/posts/validate para comprobarla con las reglas de cada red sin guardarla.t y v1 de la cabecera X-RobinReach-Signature, calcula un HMAC-SHA256 de t.raw_body con tu secreto de firma y compara ambos en tiempo constante. Rechaza marcas de tiempo de más de cinco minutos. Los ejemplos de arriba lo hacen en Ruby, Node y Python.GET /api/v1/comment_threads lista los hilos de comentarios, las conversaciones de Facebook e Instagram y las reseñas de Google, y POST /api/v1/comment_threads/{id}/reply responde uno como la marca: bajo el comentario, en privado si es un DM o en público en Google si es una reseña. Combínalo con los webhooks comment.received y message.received para responder en cuanto llega algo.Genera una clave, programa una publicación con una petición y añade un webhook. La referencia tiene todos los campos.
El acceso a la API está incluido en Bloom, Thrive y Scale.