Émettez un jeton pck_… dans Paramètres → Clés API, puis configurez TOKEN=pck_… et exécutez l'un des exemples ci-dessous. Remplacez l'URL de production par http://localhost:3000 pour le développement 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"Deux identifiants pris en charge : Authorization: Bearer pck_… (un jeton API — principal ; fonctionne pour chaque route /api/v1/*), ou un JWT de session Supabase (applications propriétaires seulement — approuver/rejeter depuis le mobile, statut de l'espace de travail). Les appelants en session appartenant à plus d'un espace de travail doivent envoyer x-workspace-id ; l'omettre renvoie 403 workspace_forbidden.
Un jeton API appartient exactement à un espace de travail, pour toujours. Un appelant avec N espaces de travail crée N jetons (un par espace de travail) pour tous les atteindre — il n'existe pas de jeton multi-espaces de travail.
Par défaut 60 requêtes/minute, budgétées indépendamment par jeton pck_, par utilisateur en session et par autorisation OAuth. Le budget d'un jeton pck_ est partagé entre cette API REST et le serveur MCP — les mêmes requêtes comptent pour les deux. Dépasser le budget renvoie 429 rate_limited avec un en-tête Retry-After (secondes avant la réinitialisation de la fenêtre). Il n'existe pas de famille d'en-têtes X-RateLimit-*.
Au sein de /api/v1 seuls des changements additifs sont livrés : nouveaux points de terminaison, nouveaux champs de requête optionnels, nouveaux champs de réponse, nouvelles valeurs d'énumération. Les clients doivent ignorer les champs et valeurs d'énumération inconnus. Les changements incompatibles sont livrés sous un nouveau préfixe de route (/api/v2), jamais comme une mutation de v1. Une opération v1 obsolète est marquée deprecated: true dans la spécification OpenAPI, listée ici, et ses propriétaires/administrateurs d'espace de travail sont avisés par courriel — l'opération continue de fonctionner pendant au moins 6 mois après cet avis avant d'être retirée.
Opérations obsolètes : aucune.
GET /api/v1/workspace/status (portée : workspace:read) renvoie aussi deux projections de transparence en lecture seule en plus de lifecycle et usage — les deux sont des clés de réponse obligatoires qui valent null lorsque l'état sous-jacent est absent, jamais omises.
support_access n'est non nul que lorsqu'une session de support de la plateforme est activement ouverte contre le propre espace de travail de l'appelant — la vue de transparence du propriétaire sur le flux d'accès au support avec consentement. Il ne contient que active, admin_email, started_at et expires_at — jamais un identifiant de session, un code de consentement, un jeton chiffré, ni les données d'un autre espace de travail.
account_deletion n'est non nul que lorsque l'utilisateur appelant a une demande de suppression de compte active (en attente ou bloquée), strictement limitée à cet appelant. Il contient scheduled et effective_at — la date avant laquelle la purge ne peut avoir lieu — afin qu'un client puisse afficher un avis de suppression en attente sans une seconde requête.
Vous préférez l'accès par MCP ? Le guide du serveur MCP explique comment connecter Claude Desktop ou un client MCP personnalisé directement - sans curl, sans tableau de bord. Requiert un plan Max ou Enterprise.
Renvoyer un accept / dismiss / snooze / resolve / approve déjà pris en compte renvoie 200 { "ok": true, "idempotent": true } - sûr à réessayer en cas de panne réseau. Le point de terminaison approve utilise CAS (comparer et échanger) pour des écritures exactement une fois vers les boutiques Shopify.
| Statut | code | Signification |
|---|---|---|
| 400 | bad_request | Le corps de la requête n'a pas pu être analysé comme JSON |
| 401 | unauthorized | Jeton manquant / inconnu / révoqué / expiré |
| 403 | insufficient_scope | Le jeton n'a pas la portée requise (le champ required l'indique) |
| 403 | forbidden_role | Approuver / rejeter seulement : le rôle de l'appelant dans l'espace de travail est inférieur à approver|admin|owner |
| 403 | token_unusable | Routes de mutation seulement : l'utilisateur ayant émis ce jeton a été supprimé - émettez un nouveau jeton |
| 403 | workspace_forbidden | Appelant avec JWT de session sans accès à l'espace de travail résolu - x-workspace-id manquant ou incorrect |
| 402 | plan_limit / email_not_confirmed / budget codes | Le plafond du plan ou la restriction de facturation a refusé l'action |
| 422 | tier_ineligible | Approuver seulement : l'écriture commerciale nécessite un plan Max ou Enterprise - mettez à niveau dans Paramètres → Facturation |
| 422 | no_commerce_integration | Approuver seulement : aucune intégration Shopify connectée pour cet espace de travail - connectez-en une dans Paramètres → Intégrations |
| 404 | not_found | Aucune ressource de ce type dans votre espace de travail |
| 409 | conflict | Transition d'état non autorisée depuis l'état actuel |
| 422 | validation_error | Le corps ou le paramètre de requête a échoué à la validation du schéma Zod (issues liste les champs) |
| 429 | rate_limited | Limite de requêtes dépassée - par jeton (pck_) ou par utilisateur (session) - respectez Retry-After |