{"openapi":"3.1.0","info":{"title":"ConsentLayer API","version":"1.0.0","description":"Consent management API for managing sites, banners, cookie categories, services, scanning, and consent records."},"servers":[{"url":"http://localhost:3001/api/v1","description":"Local development"},{"url":"https://api.consentlayer.com/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{},"parameters":{}},"paths":{"/sites":{"get":{"tags":["Sites"],"summary":"List all sites","description":"Returns all sites belonging to the authenticated organization.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of sites","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organizationId":{"type":"string","format":"uuid"},"name":{"type":"string"},"projectKey":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","organizationId","name","projectKey","createdAt","updatedAt"]}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}":{"get":{"tags":["Sites"],"summary":"Get a site by ID","description":"Returns a single site by its UUID.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Site details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organizationId":{"type":"string","format":"uuid"},"name":{"type":"string"},"projectKey":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","organizationId","name","projectKey","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/banner":{"get":{"tags":["Banner"],"summary":"Get banner configuration","description":"Returns the banner configuration for a site.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Banner configuration","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"template":{"type":"string","enum":["floating","wide_bar","modal"]},"position":{"type":"string","enum":["bottom_left","bottom_right","top_left","top_right","bottom","top","center"]},"colors":{"type":"object","additionalProperties":{"type":"string"}},"textOverrides":{"type":"object","additionalProperties":{"type":"string"}},"logoUrl":{"type":"string","nullable":true},"privacyPolicyUrl":{"type":"string","nullable":true},"defaultBehavior":{"type":"string","enum":["opt_in","opt_out","no_banner"]},"closeButtonBehavior":{"type":"string","enum":["accept_all","reject_all","dismiss"]},"cookieExpirationDays":{"type":"number"},"consentVersion":{"type":"number"},"blockingRules":{"nullable":true},"gcmExcludeGoogle":{"type":"boolean"},"shopifyIntegration":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","siteId","template","position","colors","textOverrides","logoUrl","privacyPolicyUrl","defaultBehavior","closeButtonBehavior","cookieExpirationDays","consentVersion","gcmExcludeGoogle","shopifyIntegration","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site or banner config not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}},"patch":{"tags":["Banner"],"summary":"Update banner configuration","description":"Partially updates the banner configuration for a site.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","enum":["floating","wide_bar","modal"]},"position":{"type":"string","enum":["bottom_left","bottom_right","top_left","top_right","bottom","top","center"]},"colors":{"type":"object","properties":{"primary":{"type":"string","minLength":1},"background":{"type":"string","minLength":1},"text":{"type":"string","minLength":1},"acceptButton":{"type":"string","minLength":1},"rejectButton":{"type":"string","minLength":1}}},"textOverrides":{"type":"object","properties":{"headline":{"type":"string"},"body":{"type":"string","maxLength":2000},"acceptLabel":{"type":"string"},"rejectLabel":{"type":"string"},"preferencesLabel":{"type":"string"},"privacyLabel":{"type":"string"}}},"textTranslations":{"type":"object","additionalProperties":{"type":"object","properties":{"headline":{"type":"string"},"body":{"type":"string","maxLength":2000},"acceptLabel":{"type":"string"},"rejectLabel":{"type":"string"},"preferencesLabel":{"type":"string"},"privacyLabel":{"type":"string"}}}},"privacyPolicyUrl":{"type":"string","nullable":true,"maxLength":500,"format":"uri"},"cookiePolicyUrl":{"type":"string","nullable":true,"maxLength":500,"format":"uri"},"defaultBehavior":{"type":"string","enum":["opt_in","opt_out","no_banner"]},"closeButtonBehavior":{"type":"string","enum":["accept_all","reject_all","dismiss"]},"cookieExpirationDays":{"type":"integer","minimum":1,"maximum":730}}}}}},"responses":{"200":{"description":"Updated banner configuration","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"template":{"type":"string","enum":["floating","wide_bar","modal"]},"position":{"type":"string","enum":["bottom_left","bottom_right","top_left","top_right","bottom","top","center"]},"colors":{"type":"object","additionalProperties":{"type":"string"}},"textOverrides":{"type":"object","additionalProperties":{"type":"string"}},"logoUrl":{"type":"string","nullable":true},"privacyPolicyUrl":{"type":"string","nullable":true},"defaultBehavior":{"type":"string","enum":["opt_in","opt_out","no_banner"]},"closeButtonBehavior":{"type":"string","enum":["accept_all","reject_all","dismiss"]},"cookieExpirationDays":{"type":"number"},"consentVersion":{"type":"number"},"blockingRules":{"nullable":true},"gcmExcludeGoogle":{"type":"boolean"},"shopifyIntegration":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","siteId","template","position","colors","textOverrides","logoUrl","privacyPolicyUrl","defaultBehavior","closeButtonBehavior","cookieExpirationDays","consentVersion","gcmExcludeGoogle","shopifyIntegration","createdAt","updatedAt"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site or banner config not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/categories":{"get":{"tags":["Categories"],"summary":"List categories","description":"Returns all cookie categories for a site.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"List of categories","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"isRequired":{"type":"boolean"},"isDefault":{"type":"boolean"},"sortOrder":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","siteId","slug","name","description","isRequired","isDefault","sortOrder","createdAt","updatedAt"]}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"tags":["Categories"],"summary":"Create a category","description":"Creates a new cookie category for a site. The slug is auto-generated from the name.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":500,"default":""},"nameTranslations":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"descriptionTranslations":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}}},"required":["name"]}}}},"responses":{"201":{"description":"Created category","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"isRequired":{"type":"boolean"},"isDefault":{"type":"boolean"},"sortOrder":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","siteId","slug","name","description","isRequired","isDefault","sortOrder","createdAt","updatedAt"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/categories/{catId}":{"patch":{"tags":["Categories"],"summary":"Update a category","description":"Partially updates a cookie category.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","description":"Category ID"},"required":true,"name":"catId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":500},"sortOrder":{"type":"integer","minimum":0},"nameTranslations":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"descriptionTranslations":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}}}}}}},"responses":{"200":{"description":"Updated category","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"isRequired":{"type":"boolean"},"isDefault":{"type":"boolean"},"sortOrder":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","siteId","slug","name","description","isRequired","isDefault","sortOrder","createdAt","updatedAt"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site or category not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}},"delete":{"tags":["Categories"],"summary":"Delete a category","description":"Deletes a cookie category. Default categories cannot be deleted.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","description":"Category ID"},"required":true,"name":"catId","in":"path"}],"responses":{"200":{"description":"Deletion confirmed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Cannot delete default category","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site or category not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/services":{"get":{"tags":["Services"],"summary":"List services with cookies","description":"Returns all detected services and their cookies for a site.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"List of services","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"categoryId":{"type":"string","format":"uuid"},"slug":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"privacyPolicyUrl":{"type":"string","nullable":true},"logoUrl":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"cookies":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"serviceId":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"duration":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","serviceId","name","description","duration","createdAt"]}}},"required":["id","siteId","categoryId","slug","label","description","privacyPolicyUrl","logoUrl","createdAt","updatedAt","cookies"]}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"tags":["Services"],"summary":"Create a custom service","description":"Creates a custom service with optional cookies for tracking scripts not in the library.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[a-z0-9-]+$"},"label":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":1000},"labelTranslations":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"descriptionTranslations":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"categorySlug":{"type":"string","minLength":1,"maxLength":50},"serviceUrl":{"type":"string","maxLength":500,"format":"uri"},"cookies":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"duration":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":500},"descriptionTranslations":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}}},"required":["name","duration"]}}},"required":["slug","label","categorySlug"]}}}},"responses":{"201":{"description":"Service created","content":{"application/json":{"schema":{"type":"object","properties":{"service":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"label":{"type":"string"},"categoryId":{"type":"string","format":"uuid"}},"required":["id","slug","label","categoryId"]},"cookiesCreated":{"type":"number"}},"required":["service","cookiesCreated"]}}}},"400":{"description":"Validation error or category not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"Service slug already exists on site","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/services/{serviceId}":{"delete":{"tags":["Services"],"summary":"Delete a service","description":"Deletes a service and its associated cookies.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","description":"Service ID"},"required":true,"name":"serviceId","in":"path"}],"responses":{"200":{"description":"Deletion confirmed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site or service not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/scan":{"post":{"tags":["Scanner"],"summary":"Trigger a scan","description":"Triggers a new cookie/script scan for a site. Optionally provide a specific URL to scan.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"urls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":10},"storefrontPassword":{"type":"string","minLength":1,"maxLength":100}}}}}},"responses":{"201":{"description":"Scan created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"url":{"type":"string"},"status":{"type":"string","enum":["completed","failed"]},"detectedServices":{"nullable":true},"unrecognizedScripts":{"nullable":true},"errorMessage":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","siteId","url","status","errorMessage","createdAt"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/trackers":{"get":{"tags":["Scanner"],"summary":"List trackers","description":"Trackers the latest scan found in the theme (non-essential) and their IDs. On Shopify they run before consent until the merchant moves them to a custom pixel.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Trackers","content":{"application/json":{"schema":{"type":"object","properties":{"scan":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["completed","failed"]},"error":{"type":"string","nullable":true},"at":{"type":"string"}},"required":["id","status","error","at"]},"lastCompletedAt":{"type":"string","nullable":true},"trackers":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"label":{"type":"string"},"category":{"type":"string"},"trackingIds":{"type":"array","items":{"type":"string"}}},"required":["slug","label","category","trackingIds"]}},"siteWideBlocking":{"type":"boolean"}},"required":["scan","lastCompletedAt","trackers","siteWideBlocking"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/script-blocking":{"put":{"tags":["Scanner"],"summary":"Site-wide browser blocking","description":"Turns site-wide client-side script blocking on or off. Changes the consent version, so visitors see the banner again.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"]}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/scans":{"get":{"tags":["Scanner"],"summary":"List scans","description":"Returns all scan results for a site.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"List of scan results","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"url":{"type":"string"},"status":{"type":"string","enum":["completed","failed"]},"detectedServices":{"nullable":true},"unrecognizedScripts":{"nullable":true},"errorMessage":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","siteId","url","status","errorMessage","createdAt"]}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/scans/{scanId}":{"get":{"tags":["Scanner"],"summary":"Get a scan result","description":"Returns a single scan result by its ID.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","description":"Scan ID"},"required":true,"name":"scanId","in":"path"}],"responses":{"200":{"description":"Scan result details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"url":{"type":"string"},"status":{"type":"string","enum":["completed","failed"]},"detectedServices":{"nullable":true},"unrecognizedScripts":{"nullable":true},"errorMessage":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","siteId","url","status","errorMessage","createdAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site or scan not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/scans/{scanId}/configure":{"post":{"tags":["Scanner"],"summary":"Configure services from scan","description":"Automatically creates services and cookies based on a completed scan's detected services.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","description":"Scan ID"},"required":true,"name":"scanId","in":"path"}],"responses":{"200":{"description":"Configuration result","content":{"application/json":{"schema":{"type":"object","properties":{"created":{"type":"number"},"services":{"type":"array","items":{"nullable":true}},"blockingRulesAdded":{"type":"number"}},"required":["created","services","blockingRulesAdded"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/consent-records":{"get":{"tags":["Consent Records"],"summary":"List consent records","description":"Returns paginated consent records for a site with optional date filtering.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Page number (default: 1)"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","description":"Items per page (default: 50, max: 100)"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Filter: created after this ISO date"},"required":false,"name":"from","in":"query"},{"schema":{"type":"string","description":"Filter: created before this ISO date"},"required":false,"name":"to","in":"query"}],"responses":{"200":{"description":"Paginated consent records","content":{"application/json":{"schema":{"type":"object","properties":{"records":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"visitorId":{"type":"string"},"ipCountry":{"type":"string"},"jurisdiction":{"type":"string","enum":["gdpr","ccpa","none"]},"categoriesConsented":{"type":"object","additionalProperties":{"type":"boolean"}},"gpcSignal":{"type":"boolean"},"doNotSell":{"type":"boolean"},"consentVersion":{"type":"number"},"createdAt":{"type":"string"}},"required":["id","siteId","visitorId","ipCountry","jurisdiction","categoriesConsented","gpcSignal","doNotSell","consentVersion","createdAt"]}},"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"}},"required":["records","total","page","limit"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/library/services":{"get":{"tags":["Library"],"summary":"Browse service library","description":"Returns the catalog of known services from the cookie library. Supports optional ?q= search.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"q","in":"query"}],"responses":{"200":{"description":"List of library services","content":{"application/json":{"schema":{"type":"object","properties":{"services":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"category":{"type":"string"},"logo":{"type":"string","nullable":true},"cookieCount":{"type":"number"}},"required":["slug","label","description","category","logo","cookieCount"]}}},"required":["services"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/library/services/{slug}":{"get":{"tags":["Library"],"summary":"Get library service details","description":"Returns full details and cookies for a service from the library.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"Service details with cookies","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"category":{"type":"string"},"logo":{"type":"string","nullable":true},"serviceUrl":{"type":"string","nullable":true},"cookies":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"duration":{"type":"string"},"description":{"type":"string"}},"required":["name","duration","description"]}}},"required":["slug","label","description","category","logo","serviceUrl","cookies"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Service not found in library","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/services/import":{"post":{"tags":["Services"],"summary":"Import a library service","description":"Imports a service from the cookie library into a site: the service row, all its documented cookies, and the script-blocking rules that keep it from loading before consent. `blockingRulesAdded` reports how many rules were added — 0 when the service is in a required category, is already covered by a built-in rule, or has no known script patterns.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":100},"categorySlug":{"type":"string","minLength":1,"maxLength":50}},"required":["slug"]}}}},"responses":{"201":{"description":"Service imported","content":{"application/json":{"schema":{"type":"object","properties":{"service":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"label":{"type":"string"},"categoryId":{"type":"string","format":"uuid"}},"required":["id","slug","label","categoryId"]},"cookiesCreated":{"type":"number"},"blockingRulesAdded":{"type":"number"}},"required":["service","cookiesCreated","blockingRulesAdded"]}}}},"400":{"description":"Category not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site or library service not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"Service already exists on site","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/sites/{id}/setup-snippet":{"get":{"tags":["Setup"],"summary":"Get setup snippet","description":"Generates a ready-to-use integration code snippet for the site.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Site ID","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["script","react","next"],"default":"script"},"required":false,"name":"framework","in":"query"}],"responses":{"200":{"description":"Setup snippet","content":{"application/json":{"schema":{"type":"object","properties":{"framework":{"type":"string","enum":["script","react","next"]},"code":{"type":"string"},"instructions":{"type":"string"}},"required":["framework","code","instructions"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}}}}