Emite un token pck_… en Configuración → Claves de API, luego configura TOKEN=pck_… y ejecuta cualquiera de los ejemplos a continuación. Reemplaza la URL de producción por http://localhost:3000 para desarrollo local.
# List recent runs (scope: runs:read)
curl -s https://www.margintide.com/api/v1/runs \
-H "Authorization: Bearer $TOKEN"
# Trigger a run (scope: runs:trigger)
curl -s -X POST https://www.margintide.com/api/v1/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"subset_tags": ["core-skus"]}'
# List recommendations (scope: recommendations:read)
curl -s "https://www.margintide.com/api/v1/recommendations?status=new" \
-H "Authorization: Bearer $TOKEN"
# Accept a recommendation (scope: recommendations:write)
curl -s -X POST https://www.margintide.com/api/v1/recommendations/$REC_ID/accept \
-H "Authorization: Bearer $TOKEN"
# Approve a pending_approval recommendation - triggers Shopify write-back
# (scope: recommendations:approve - Max / Enterprise plan required)
curl -s -X POST https://www.margintide.com/api/v1/recommendations/$REC_ID/approve \
-H "Authorization: Bearer $TOKEN"
# Reject a pending_approval recommendation with a reason
# (scope: recommendations:approve)
curl -s -X POST https://www.margintide.com/api/v1/recommendations/$REC_ID/reject \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason": "price too aggressive for Q3 margin target"}'
# Snooze an alert (scope: alerts:write)
curl -s -X POST https://www.margintide.com/api/v1/alerts/$ALERT_ID/snooze \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"snooze_until": "2026-07-01T00:00:00Z", "reason": "supplier renegotiation"}'
# List catalog items (scope: catalog:read)
curl -s https://www.margintide.com/api/v1/catalog/items \
-H "Authorization: Bearer $TOKEN"
# Export report data (scope: reports:read)
curl -s https://www.margintide.com/api/v1/reports/export \
-H "Authorization: Bearer $TOKEN"Dos credenciales admitidas: Authorization: Bearer pck_… (un token de API — principal; funciona con cada ruta /api/v1/*), o un JWT de sesión de Supabase (solo apps propias — aprobar/rechazar desde el móvil, estado del espacio de trabajo). Los llamados con sesión que pertenecen a más de un espacio de trabajo deben enviar x-workspace-id; omitirlo devuelve 403 workspace_forbidden.
Un token de API pertenece exactamente a un espacio de trabajo, para siempre. Un llamador con N espacios de trabajo crea N tokens (uno por espacio de trabajo) para alcanzarlos todos — no existe un token entre espacios de trabajo.
Por defecto 60 solicitudes/minuto, presupuestadas de forma independiente por token pck_, por usuario de sesión y por concesión de OAuth. El presupuesto de un token pck_ se comparte entre esta API REST y el servidor MCP — las mismas solicitudes cuentan para ambos. Superar el presupuesto devuelve 429 rate_limited con un encabezado Retry-After (segundos hasta que se reinicie la ventana). No existe la familia de encabezados X-RateLimit-*.
Dentro de /api/v1 solo se envían cambios aditivos: nuevos puntos de conexión, nuevos campos de solicitud opcionales, nuevos campos de respuesta, nuevos valores de enumeración. Los clientes deben ignorar los campos y valores de enumeración desconocidos. Los cambios incompatibles se envían bajo un nuevo prefijo de ruta (/api/v2), nunca como una mutación de v1. Una operación v1 obsoleta se marca como deprecated: true en la especificación OpenAPI, se enumera aquí, y se notifica por correo a los propietarios/administradores del espacio de trabajo — la operación sigue funcionando durante al menos 6 meses después de ese aviso antes de eliminarse.
Operaciones obsoletas: ninguna.
GET /api/v1/workspace/status (alcance: workspace:read) también devuelve dos proyecciones de transparencia de solo lectura junto con lifecycle y usage — ambas son claves de respuesta obligatorias que son null cuando el estado subyacente está ausente, nunca se omiten.
support_access es no nulo solo mientras una sesión de soporte de la plataforma está activamente abierta contra el propio espacio de trabajo del llamador — la vista de transparencia del propietario sobre el flujo de acceso de soporte con consentimiento. Solo contiene active, admin_email, started_at y expires_at — nunca un id de sesión, código de consentimiento, token cifrado, ni datos de ningún otro espacio de trabajo.
account_deletion es no nulo solo mientras el usuario que llama tiene una solicitud de eliminación de cuenta activa (pendiente o bloqueada), limitada estrictamente a ese llamador. Contiene scheduled y effective_at — la fecha antes de la cual no se realizará la purga — para que un cliente pueda mostrar un aviso de eliminación pendiente sin una segunda solicitud.
¿Prefieres el acceso por MCP? La guía del servidor MCP explica cómo conectar Claude Desktop o un cliente MCP personalizado directamente - sin curl ni panel. Requiere un plan Max o Enterprise.
Reenviar un accept / dismiss / snooze / resolve / approve que ya surtió efecto devuelve 200 { "ok": true, "idempotent": true } - seguro para reintentar ante fallas de red. El endpoint de aprobación usa CAS (comparar e intercambiar) para escrituras exactamente una vez en tiendas Shopify.
| Estado | código | Significado |
|---|---|---|
| 400 | bad_request | El cuerpo de la solicitud no pudo analizarse como JSON |
| 401 | unauthorized | Token faltante / desconocido / revocado / vencido |
| 403 | insufficient_scope | El token no tiene el alcance requerido (el campo required lo indica) |
| 403 | forbidden_role | Solo aprobar / rechazar: el rol del llamador en el espacio de trabajo está por debajo de approver|admin|owner |
| 403 | token_unusable | Solo rutas de mutación: el usuario que emitió este token fue eliminado - emite un token nuevo |
| 403 | workspace_forbidden | Llamador con JWT de sesión sin acceso al espacio de trabajo resuelto - falta o es incorrecto x-workspace-id |
| 402 | plan_limit / email_not_confirmed / budget codes | El límite del plan o la restricción de facturación rechazó la acción |
| 422 | tier_ineligible | Solo aprobar: la escritura de comercio requiere plan Max o Enterprise - actualiza en Configuración → Facturación |
| 422 | no_commerce_integration | Solo aprobar: no hay integración de Shopify conectada para este espacio de trabajo - conecta una en Configuración → Integraciones |
| 404 | not_found | No existe tal recurso en tu espacio de trabajo |
| 409 | conflict | Transición de estado no permitida desde el estado actual |
| 422 | validation_error | El cuerpo o parámetro de consulta no pasó la validación del esquema Zod (issues enumera los campos) |
| 429 | rate_limited | Límite de solicitudes superado - por token (pck_) o por usuario (sesión) - respete Retry-After |