{"openapi":"3.1.0","info":{"title":"ApexPentest GTM API","version":"1.0.0","description":"API first-party pour lire les comptes et signaux, ingérer les événements GTM et exporter le warehouse. Toutes les routes métier exigent une clé à portée explicite.","contact":{"url":"https://apexpentest.com/#contact"}},"servers":[{"url":"https://localhost:3001","description":"Production"}],"tags":[{"name":"Accounts","description":"Comptes consolidés"},{"name":"Signals","description":"Signaux GTM entrants et sortants"},{"name":"Events","description":"Événements first-party"},{"name":"Warehouse","description":"Export analytique incrémental"}],"security":[{"bearerApiKey":[]}],"paths":{"/api/v1/accounts":{"get":{"tags":["Accounts"],"summary":"Lister les comptes","operationId":"listAccounts","security":[{"bearerApiKey":["accounts:read"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":100}},{"name":"updated_after","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Page de comptes.","headers":{"RateLimit-Limit":{"description":"Quota par minute de la clé.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requêtes restantes dans la fenêtre minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Fin de fenêtre minute, epoch UNIX en secondes.","schema":{"type":"integer"}},"X-Request-Id":{"description":"Identifiant de corrélation de la requête.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","count","requestId"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Account"}},"count":{"type":"integer"},"requestId":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/signals":{"get":{"tags":["Signals"],"summary":"Lister les signaux","operationId":"listSignals","security":[{"bearerApiKey":["signals:read"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":100}},{"name":"detected_after","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Page de signaux.","headers":{"RateLimit-Limit":{"description":"Quota par minute de la clé.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requêtes restantes dans la fenêtre minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Fin de fenêtre minute, epoch UNIX en secondes.","schema":{"type":"integer"}},"X-Request-Id":{"description":"Identifiant de corrélation de la requête.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Signal"}},"count":{"type":"integer"},"requestId":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Signals"],"summary":"Ingestérer un signal","operationId":"createSignal","security":[{"bearerApiKey":["signals:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalInput"}}}},"responses":{"201":{"description":"Signal créé.","headers":{"RateLimit-Limit":{"description":"Quota par minute de la clé.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requêtes restantes dans la fenêtre minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Fin de fenêtre minute, epoch UNIX en secondes.","schema":{"type":"integer"}},"X-Request-Id":{"description":"Identifiant de corrélation de la requête.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":["string","null"],"format":"uuid"},"deduplicated":{"type":"boolean"},"requestId":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/events":{"post":{"tags":["Events"],"summary":"Ingestérer un événement","operationId":"createEvent","security":[{"bearerApiKey":["events:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventInput"}}}},"responses":{"201":{"description":"Événement persisté et compte résolu.","headers":{"RateLimit-Limit":{"description":"Quota par minute de la clé.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requêtes restantes dans la fenêtre minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Fin de fenêtre minute, epoch UNIX en secondes.","schema":{"type":"integer"}},"X-Request-Id":{"description":"Identifiant de corrélation de la requête.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/warehouse":{"get":{"tags":["Warehouse"],"summary":"Exporter le journal analytique NDJSON","operationId":"exportWarehouse","security":[{"bearerApiKey":["warehouse:read"]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":5000,"default":1000}}],"responses":{"200":{"description":"NDJSON. Le curseur suivant est renvoyé dans X-Apex-Next-Cursor.","headers":{"RateLimit-Limit":{"description":"Quota par minute de la clé.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requêtes restantes dans la fenêtre minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Fin de fenêtre minute, epoch UNIX en secondes.","schema":{"type":"integer"}},"X-Request-Id":{"description":"Identifiant de corrélation de la requête.","schema":{"type":"string"}},"X-Apex-Next-Cursor":{"schema":{"type":"string"},"description":"Curseur opaque de la page suivante."},"X-Apex-Has-More":{"schema":{"type":"boolean"}}},"content":{"application/x-ndjson":{"schema":{"type":"string"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}}},"webhooks":{"crmEvent":{"post":{"summary":"Événement CRM signé","description":"Les endpoints configurés reçoivent X-Apex-Event, X-Apex-Delivery, X-Apex-Timestamp et X-Apex-Signature (HMAC-SHA256).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id","type","createdAt","data"],"properties":{"id":{"type":"string"},"type":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"data":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Accusé de réception."}}}}},"components":{"securitySchemes":{"bearerApiKey":{"type":"http","scheme":"bearer","bearerFormat":"apx_live_*","description":"Clé créée dans Paramètres → API & webhooks. Les portées sont vérifiées à chaque requête."}},"schemas":{"Account":{"type":"object","required":["id","name","lifecycle_stage","status","total_score"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"domain":{"type":["string","null"]},"website":{"type":["string","null"],"format":"uri"},"industry":{"type":["string","null"]},"employee_band":{"type":["string","null"]},"country":{"type":["string","null"]},"lifecycle_stage":{"type":"string"},"status":{"type":"string"},"tier":{"type":"string"},"fit_score":{"type":"integer","minimum":0,"maximum":100},"intent_score":{"type":"integer","minimum":0,"maximum":100},"engagement_score":{"type":"integer","minimum":0,"maximum":100},"total_score":{"type":"integer","minimum":0,"maximum":100},"updated_at":{"type":"string","format":"date-time"}}},"Signal":{"type":"object","required":["id","account_id","type","strength","title","source"],"properties":{"id":{"type":"string","format":"uuid"},"account_id":{"type":"string","format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid"},"type":{"type":"string"},"strength":{"type":"integer","minimum":0,"maximum":100},"title":{"type":"string"},"description":{"type":["string","null"]},"source":{"type":"string"},"evidence_json":{"type":"string"},"status":{"type":"string"},"detected_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"}}},"SignalInput":{"type":"object","required":["accountId","type","title","source"],"properties":{"accountId":{"type":"string","format":"uuid"},"contactId":{"type":["string","null"],"format":"uuid"},"type":{"type":"string","maxLength":100},"strength":{"type":"integer","minimum":0,"maximum":100},"title":{"type":"string","maxLength":240},"description":{"type":["string","null"],"maxLength":2000},"source":{"type":"string","maxLength":100},"evidence":{"type":"object","additionalProperties":true},"dedupeKey":{"type":"string","maxLength":500},"detectedAt":{"type":"string","format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"}}},"EventInput":{"type":"object","required":["name","domain"],"properties":{"name":{"type":"string","maxLength":120},"domain":{"type":"string","maxLength":253},"path":{"type":["string","null"],"maxLength":1000},"metadata":{"type":["object","null"],"additionalProperties":true}}},"Error":{"type":"object","required":["error","requestId"],"properties":{"error":{"type":"string"},"requestId":{"type":"string"}}}},"responses":{"BadRequest":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Bearer token absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Clé invalide, expirée ou portée absente.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Quota minute ou journalier dépassé.","headers":{"RateLimit-Limit":{"description":"Quota par minute de la clé.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requêtes restantes dans la fenêtre minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Fin de fenêtre minute, epoch UNIX en secondes.","schema":{"type":"integer"}},"X-Request-Id":{"description":"Identifiant de corrélation de la requête.","schema":{"type":"string"}},"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}