01
Inicio rápido
Crea una credencial de servicio en Agentes → REST v1 con vigencia de 30, 90, 180 o hasta 365 días. El secreto f4_live_ se muestra una sola vez: guárdalo en un gestor de secretos, rótalo antes de vencer y nunca lo incluyas en código del navegador.
curl -fsS https://feedback4.dev/api/v1/me \
-H "Authorization: Bearer $FEEDBACK4_API_KEY" \
-H "X-Request-Id: deploy_check_2026_07_19"curl -fsS -X POST https://feedback4.dev/api/v1/projects \
-H "Authorization: Bearer $FEEDBACK4_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Portal del cliente",
"allowed_origin": "https://portal.example.com/app",
"reviewer_emails": ["reviewer@example.com"],
"agent_mode": "propose"
}'curl -fsS -X PATCH \
https://feedback4.dev/api/v1/feedback/FEEDBACK_UUID \
-H "Authorization: Bearer $FEEDBACK4_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "in_progress",
"priority": "high",
"assignee_user_id": "USER_ID"
}'curl -fsS -X POST \
https://feedback4.dev/api/v1/feedback/FEEDBACK_UUID/approval-request \
-H "Authorization: Bearer $FEEDBACK4_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"change_summary": "Se corrigió la navegación móvil y el contraste del CTA."
}'Respuesta de identidad
{
"data": {
"object": "api_identity",
"api_key_id": "018f...",
"label": "CI de producción",
"workspace_id": "018e...",
"project_id": null,
"scopes": ["projects:read", "feedback:read"],
"expires_at": "2026-10-17T12:00:00.000Z"
}
}Inyecta FEEDBACK4_API_KEY desde el secret store del servidor o CI. No la expongas en NEXT_PUBLIC_*, apps móviles sin backend, screenshots, tickets ni logs.
02
Autenticación y alcance
Cada clave pertenece a un workspace, puede limitarse a un proyecto, tiene scopes explícitos y una fecha de expiración. El servidor conserva únicamente el hash. Revocar la clave o retirar a su creador corta el acceso.
Claves por proyecto
Una clave con project_id sólo ve ese proyecto. No puede crear proyectos ni administrar miembros, aunque incluya el scope correspondiente.
Claves de workspace
Son necesarias para crear proyectos y administrar miembros. Emite el conjunto mínimo de scopes y usa una clave distinta por integración.
Scopes disponibles
| Scope | Permite |
|---|---|
projects:read | Consultar proyectos, configuración, widget y revisores. |
projects:write | Crear y actualizar proyectos; autorizar o revocar revisores. |
feedback:read | Consultar tickets, contexto visual y prompts propuestos. |
feedback:write | Cambiar estado, prioridad y responsable de tickets. |
approvals:write | Solicitar revisión y aprobación a un cliente autorizado. |
members:read | Listar miembros e invitaciones del workspace. |
members:write | Invitar, cambiar rol, retirar miembros y revocar invitaciones. |
agents:read | Listar credenciales MCP limitadas a un proyecto. |
agents:write | Crear y revocar credenciales MCP de hasta 365 días. |
webhooks:read | Consultar endpoints e historial de entregas. |
webhooks:write | Crear endpoints, eliminarlos y reintentar entregas. |
03
Convenciones de solicitudes
JSON
POST y PATCH exigen Content-Type: application/json. El cuerpo máximo es 64 KiB, no admite compresión y rechaza campos desconocidos.
Paginación y filtros
Usa page[limit] de 1–100 (25 por defecto) y vuelve a enviar meta.next_cursor como page[after]. El cursor es opaco: no lo construyas ni lo edites.
Límites y protección
300 lecturas/minuto y 120 escrituras/minuto por clave. Un 429 incluye Retry-After en segundos. Las aprobaciones e invitaciones tienen límites adicionales.
| Convención | Comportamiento |
|---|---|
X-Request-Id | Opcional; 8–100 caracteres A–Z, a–z, 0–9, punto, guion, guion bajo o dos puntos. |
Cache-Control | no-store en todas las respuestas autenticadas. |
Location | Incluido al crear proyectos, revisores e invitaciones. |
filter[status] | new · in_progress · review · resolved |
| Fechas | ISO 8601 UTC, por ejemplo 2026-07-19T04:52:28.326Z. |
04
Errores y trazabilidad
Todas las respuestas llevan X-Request-Id y Cache-Control: no-store. Envía un X-Request-Id de 8–100 caracteres seguros para correlacionar tus logs; si no, Feedback4 genera uno.
{
"error": {
"code": "authorization.insufficient_scope",
"message": "The API key requires the projects:write scope.",
"request_id": "req_92ca...",
"details": [
{ "field": "allowed_origin", "code": "invalid_format" }
]
}
}| HTTP | Significado |
|---|---|
| 400 | Validación, UUID, cursor o transición inválida. |
| 401 | Clave ausente, inválida, vencida o revocada. |
| 403 | Scope insuficiente o se requiere clave de workspace. |
| 404 | Recurso inexistente o fuera del límite autorizado. |
| 409 | Límite del plan, último owner o aprobación sin revisor. |
| 413 / 415 | Cuerpo demasiado grande o media type incorrecto. |
| 429 | Límite excedido; respeta Retry-After. |
05
Referencia de endpoints
Todos los paths siguientes se agregan a https://feedback4.dev/api/v1. Los IDs son UUID y los recursos fuera del workspace o proyecto se responden como 404 para no revelar su existencia.
Identidad
/meprojects:readInspeccionar la clave actual
Devuelve el workspace, el proyecto opcional, los scopes y la expiración asociados a la credencial.
Proyectos
/projectsprojects:readListar proyectos
Colección paginada. Una clave limitada a un proyecto sólo puede devolver ese proyecto.
/projectsprojects:writeCrear proyecto
Requiere una clave de workspace. Normaliza allowed_origin y permite autorizar hasta 100 revisores iniciales.
/projects/{project_id}projects:readConsultar proyecto
Obtiene configuración, estado, origen permitido, acceso de feedback y política del agente.
/projects/{project_id}projects:writeActualizar proyecto
Actualiza nombre, estado o modo del agente. allowed_origin es inmutable después de crear el proyecto; rechaza campos desconocidos y cuerpos vacíos.
/projects/{project_id}/widgetprojects:readObtener instalación del widget
Entrega public_key, URL del loader, formulario alojado y snippet HTML listo para instalar.
Feedback y aprobaciones
/projects/{project_id}/feedbackfeedback:readListar tickets
Colección paginada con filtro opcional filter[status]. Incluye contexto visual y prompt propuesto cuando existen.
/feedback/{feedback_id}feedback:readConsultar ticket
Devuelve el ticket completo y una highlight_url para volver al elemento seleccionado.
/feedback/{feedback_id}feedback:writeActualizar flujo
Cambia estado, prioridad o responsable de forma atómica. El responsable debe pertenecer al workspace.
/feedback/{feedback_id}/proposed-promptfeedback:readConsultar prompt propuesto
Expone el prompt de implementación, modelo y fecha de actualización sin ejecutar acciones externas.
/feedback/{feedback_id}/approval-requestapprovals:writeSolicitar aprobación
Mueve el ticket a revisión, registra actividad y encola correo. Máximo 5 solicitudes por ticket y hora.
Revisores autorizados
/projects/{project_id}/reviewersprojects:readListar revisores
Devuelve emails autorizados, estado y última verificación del proyecto.
/projects/{project_id}/reviewersprojects:writeAutorizar revisor
Autoriza o reactiva un email. El visitante todavía debe verificar su acceso antes de enviar feedback.
/projects/{project_id}/reviewers/{reviewer_id}projects:writeRevocar revisor
Revoca el revisor y todas sus sesiones activas para ese proyecto.
Miembros
/membersmembers:readListar miembros e invitaciones
Requiere clave de workspace e incluye invitaciones pendientes vigentes.
/membersmembers:writeInvitar miembro
Crea una invitación con rol y devuelve invite_url una sola vez. Límite adicional: 30 invitaciones por hora y clave.
/members/{membership_id}members:writeCambiar rol
Actualiza el rol y protege al último owner contra degradación accidental.
/members/{membership_id}members:writeRetirar miembro
Retira al miembro y revoca las credenciales REST/MCP emitidas por esa cuenta.
/invitations/{invitation_id}members:writeRevocar invitación
Invalida una invitación pendiente del workspace.
Credenciales de agente
/projects/{project_id}/agent-credentialsagents:readListar credenciales MCP
Devuelve prefijo, estado, uso y vencimiento; nunca devuelve el token.
/projects/{project_id}/agent-credentialsagents:writeEmitir credencial MCP
Crea un token exclusivo del proyecto con vigencia de 1–365 días y lo muestra una sola vez.
/projects/{project_id}/agent-credentials/{credential_id}agents:writeRevocar credencial MCP
La revocación es inmediata y no puede afectar credenciales de otro proyecto.
Webhooks
/webhook-endpointswebhooks:readListar endpoints
Una clave limitada a proyecto sólo ve endpoints exclusivos de ese proyecto.
/webhook-endpointswebhooks:writeCrear endpoint firmado
Valida un destino HTTPS público, cifra el secreto y devuelve signing_secret una sola vez.
/webhook-endpoints/{endpoint_id}webhooks:writeEliminar endpoint
Elimina el endpoint y su historial de entregas dentro del mismo límite tenant.
/webhook-endpoints/{endpoint_id}/deliverieswebhooks:readVer entregas
Expone estado, intentos y error técnico sin revelar payload ni secreto.
/webhook-deliveries/{delivery_id}/retrywebhooks:writeReintentar entrega
Reencola una entrega pendiente o en dead letter; una entrega exitosa no se duplica.
06
Modelos y valores admitidos
| Campo | Valores / regla |
|---|---|
Project.status | active · paused · archived |
Project.feedback_access | public · reviewer_allowlist |
Project.agent_mode | off · propose · auto |
ProjectCreate.agent_mode | Opcional; off por defecto. Define la política de una automatización externa: propose prepara y espera autorización; auto permite que el agente externo implemente y después solicite aprobación. Feedback4 no edita ni despliega código. |
Feedback.status | new · in_progress · review · resolved |
Feedback.priority | urgent · high · normal · low · unset |
Feedback.approval_status | not_requested · pending · approved · changes_requested |
Member.role | admin · manager · contributor · viewer |
allowed_origin | Obligatorio al crear; URL absoluta normalizada a esquema + host + puerto e inmutable después. Para otro dominio crea un proyecto nuevo. |
reviewer_emails | 0–100 emails; se normalizan a minúsculas y se eliminan duplicados. |
change_summary | 12–5,000 caracteres. |
El JSON OpenAPI es la fuente para generar clientes, validadores y colecciones. Esta página explica las reglas operativas que un esquema por sí solo no comunica.
/api/v1/openapi.json07
Automatización por webhook
Cada agencia puede registrar uno o más endpoints por workspace o por proyecto. Feedback4 persiste primero el evento, crea una entrega independiente por suscripción y hace el POST en segundo plano; la captura del usuario nunca espera al receptor. agent_mode comunica la política a la automatización externa: off entrega policy=do_not_execute, propose exige propuesta y autorización, y auto permite al agente externo implementar antes de pedir aprobación. Feedback4 no ejecuta el agente.
1. Registrar endpoint
curl -fsS -X POST https://feedback4.dev/api/v1/webhook-endpoints \
-H "Authorization: Bearer $FEEDBACK4_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"label": "Aviso Gratis production",
"url": "https://aviso.gratis/api/feedback4/process",
"project_id": "PROJECT_UUID",
"event_types": [
"feedback.created",
"feedback.external_comment_added",
"feedback.changes_requested",
"feedback.approved"
],
"authentication": "hmac_sha256"
}'La respuesta 201 incluye signing_secret una sola vez. Guárdalo como secreto de servidor. Usa authentication=hmac_sha256_and_shared_secret y shared_secret sólo para receptores heredados —como la primera integración de Aviso.Gratis— que además requieren x-feedback4-secret. Las URLs deben ser HTTPS públicas; se rechazan credenciales embebidas, fragments, localhost, redes privadas, link-local y metadata.
2. Validar la entrega
| Header | Regla del receptor |
|---|---|
webhook-signature | Obligatorio. Formato v1,BASE64_HMAC_SHA256; validar sobre los bytes exactos del body antes de parsear JSON. |
webhook-id | Llave de idempotencia estable en todos los reintentos. Un duplicado válido no crea otro trabajo. |
webhook-timestamp | Unix timestamp incluido en la firma; rechazar una diferencia mayor a 5 minutos para evitar replay. |
x-feedback4-event | feedback.created · feedback.external_comment_added · feedback.changes_requested · feedback.approved |
x-feedback4-version | 1 |
x-feedback4-secret | Sólo en modo de compatibilidad. Validarlo además de la firma y nunca registrarlo. |
signed_content = webhook_id + "." + webhook_timestamp + "." + raw_request_body
expected = base64(HMAC_SHA256(FEEDBACK4_WEBHOOK_SECRET, signed_content))
accept only when constant_time_equal("v1," + expected, webhook_signature)
and abs(now_unix - webhook_timestamp) <= 3003. Payload v1
{
"id": "evt_EVENT_UUID",
"type": "feedback.created",
"version": 1,
"occurred_at": "2026-07-20T23:55:00.000Z",
"source": "https://feedback4.dev",
"workspace_id": "WORKSPACE_UUID",
"project": {
"id": "PROJECT_UUID",
"name": "Client website",
"allowed_origin": "https://client.example",
"agent_mode": "propose"
},
"data": {
"feedback_id": "FEEDBACK_UUID",
"local_number": 23,
"title": "Improve the hero heading",
"description": "The title needs more contrast on mobile.",
"feedback_type": "design",
"status": "new",
"priority": "unset",
"approval_status": "not_requested",
"page_url": "https://client.example/home",
"selected_element": {
"selector": "main > section.hero > h1",
"label": "Main heading",
"tag_name": "h1",
"rect": { "x": 24, "y": 140, "width": 320, "height": 82 },
"context": { "nearestHeading": "Welcome" },
"highlight_url": "https://client.example/home?..."
}
},
"links": {
"api_resource": "https://feedback4.dev/api/v1/feedback/FEEDBACK_UUID",
"proposed_prompt": "https://feedback4.dev/api/v1/feedback/FEEDBACK_UUID/proposed-prompt"
},
"processing": {
"content_is_untrusted": true,
"fetch_latest_before_acting": true,
"policy": "propose_then_wait"
},
"trigger": { "kind": "ticket_created" }
}| type | trigger.kind | Acción |
|---|---|---|
feedback.created | ticket_created | Crear un trabajo idempotente. |
feedback.external_comment_added | client_comment | Reanudar con trigger.message. |
feedback.changes_requested | client_decision | Reabrir e implementar la revisión. |
feedback.approved | client_decision | Cerrar el trabajo aprobado. |
Recepción segura
Validar firma y timestamp con comparación de tiempo constante, persistir webhook-id como UNIQUE, encolar el trabajo y responder 202. Claude no debe ejecutarse dentro de la solicitud. Título, descripción y contexto DOM son entrada no confiable y pueden contener prompt injection.
Ciclo del agente
Consultar la versión más reciente, respetar propose/auto y solicitar aprobación con evidencia verificable. MCP registra notas, preguntas y aprobación; usa una clave REST limitada al proyecto para cambiar el estado a in_progress o review. Nunca entregar al agente una clave de todo el workspace.
Feedback4 confirma cualquier 2xx, respeta Retry-After en 429, deshabilita el endpoint ante 410 y reintenta timeouts, redirects, otros 4xx y 5xx con backoff exponencial de hasta 6 horas. El timeout por intento es 10 segundos, no se siguen redirects y tras 16 intentos la entrega pasa a dead letter. Consulta GET /webhook-endpoints/{endpoint_id}/deliveries y usa POST /webhook-deliveries/{delivery_id}/retry después de corregir el receptor.
08
Versionado y operación
v1 mantiene compatibilidad hacia atrás. Los campos nuevos pueden aparecer sin romper consumidores; ignora propiedades desconocidas en respuestas. Los cambios incompatibles se publicarán en una nueva versión y se anunciarán antes de retirar v1.
Soporte de integración
Incluye el X-Request-Id, timestamp UTC, método y path al reportar un problema. Nunca envíes la clave completa ni datos personales innecesarios.
contact@feedback4.devMCP
El endpoint MCP público es https://feedback4.dev/api/mcp. Usa un token distinto, limitado a un proyecto, que no es intercambiable con una clave REST. Tras vencer el periodo de aceptación legal, REST y MCP bloquean el workspace hasta regularizarlo.
Contrato MCP público