{"openapi":"3.1.0","info":{"title":"BatteryComply API","description":"Public API for EU Battery Regulation (EU) 2023/1542 compliance audits and Digital Battery Passport issuance under Article 77 / Annex XIII.\n\n**Audit endpoint** (`/api/v1/check`) takes a single PDF (DoC, spec sheet, test report, etc.) and returns a structured compliance verdict against the ten checks described at https://batterycomply.com/how-we-audit.\n\n**Passport endpoints** (`/api/v1/passport/*`) extract Annex XIII data, assemble JSON-LD 1.1, and return a QR-encoded resolver URL (ISO/IEC 18004) suitable for printing on a battery label.\n\nStage 6a (preview): no authentication; rate-limited at the network layer. Stage 6b will introduce API keys + per-call metering. Until then, please be polite — at most a few requests per minute.","contact":{"name":"BatteryComply","url":"https://batterycomply.com/","email":"info@batterycomply.com"},"license":{"name":"Terms of Service","url":"https://batterycomply.com/terms"},"version":"1.0.0"},"servers":[{"url":"https://batterycomply-api.onrender.com","description":"Production"}],"paths":{"/health":{"get":{"tags":["ops"],"summary":"Liveness probe.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/analyze":{"post":{"tags":["internal"],"summary":"Website upload handler. Use /api/v1/check for third-party integrations.","operationId":"analyze_api_analyze_post","parameters":[{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"da","title":"Lang"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_analyze_api_analyze_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/report/{report_id}":{"get":{"tags":["internal"],"summary":"Fetch a previously stored audit report by ID.","operationId":"get_report_api_report__report_id__get","parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/passport/build":{"post":{"tags":["internal"],"summary":"Website upload handler. Use /api/v1/passport/build for third-party integrations.","operationId":"passport_build_api_passport_build_post","parameters":[{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"en","title":"Lang"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_passport_build_api_passport_build_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/passport/{passport_id}":{"get":{"tags":["internal"],"summary":"Fetch a stored Battery Passport by ID (gated unless unlocked).","operationId":"get_passport_endpoint_api_passport__passport_id__get","parameters":[{"name":"passport_id","in":"path","required":true,"schema":{"type":"string","title":"Passport Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/passport/{passport_id}/resolve":{"get":{"tags":["v1: passport"],"summary":"Public passport resolver. This is what battery QR codes point at.","description":"Public resolver — what the QR code on the battery resolves to.\n\nContent negotiation:\n  - `Accept: application/ld+json` → returns the public-tier JSON-LD\n    (Part B / Part C stripped) regardless of unlock state. This is what\n    scanners and aggregators read.\n  - Default → returns a small JSON envelope with `viewer_url` so the\n    Netlify-hosted `passport.html` can render localized chrome.\n\nNOTE: Stage 5b ships with a single-tier resolver that always returns the\npublic-tier projection. Authority/recycler login flows that unlock Part B\nand Part C arrive in a later stage (see PASSPORT_NOTES.md \"Open\nquestions\" #5).","operationId":"resolve_passport_api_passport__passport_id__resolve_get","parameters":[{"name":"passport_id","in":"path","required":true,"schema":{"type":"string","title":"Passport Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/feedback":{"post":{"tags":["internal"],"summary":"Website feedback pill.","operationId":"post_feedback_api_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/check":{"post":{"tags":["v1: audit"],"summary":"Run a battery compliance audit on a single PDF.","description":"Upload a Declaration of Conformity, technical file, spec sheet, or test report. Returns a structured verdict (`APPROVED` / `CONDITIONAL` / `NOT_APPROVED`), per-check findings against EU 2023/1542, and a list of recommended actions.\n\n**Gating:** Stage 6a returns the gated shape (counts + teaser) just like the website endpoint. Pass `?include_full=true` once Stage 6b API keys are live to receive the full `checks[]` and `recommended_actions[]` arrays. Until then, fetch the unlocked report via `GET /api/report/{id}` after a manual unlock has been arranged.\n\nMethodology and Article citations: https://batterycomply.com/how-we-audit","operationId":"v1_check_api_v1_check_post","parameters":[{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"en","title":"Lang"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_v1_check_api_v1_check_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/passport/build":{"post":{"tags":["v1: passport"],"summary":"Build a Digital Battery Passport (Annex XIII) from one PDF.","description":"Upload a battery technical file (manufacturer datasheet + DoC + optional UN 38.3 summary + optional carbon-footprint declaration). Returns a passport ID, completeness ratio against today's required-field set, and a QR-code resolver URL conforming to ISO/IEC 18004 + ISO/IEC 15459 UPI.\n\n**Scope:** EU Regulation (EU) 2023/1542 Article 77 + Annex XIII. Categories covered: LMT, industrial > 2 kWh, EV. Out-of-scope categories return `out_of_scope: true` with a localized reason and no charge.\n\nJSON-LD `@context` anchors schema.org + https://batterycomply.com/passport-context.jsonld.","operationId":"v1_passport_build_api_v1_passport_build_post","parameters":[{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"en","title":"Lang"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_v1_passport_build_api_v1_passport_build_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/passport/{passport_id}":{"get":{"tags":["v1: passport"],"summary":"Fetch a stored Battery Passport by ID.","description":"Returns the gated shape (counts + teaser, no Annex XIII values) until the passport has been unlocked. Once unlocked, returns the full JSON-LD document plus the raw extraction envelope (per-field confidence and provenance).","operationId":"v1_passport_get_api_v1_passport__passport_id__get","parameters":[{"name":"passport_id","in":"path","required":true,"schema":{"type":"string","title":"Passport Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/passport/{passport_id}/resolve":{"get":{"tags":["v1: passport"],"summary":"Public passport resolver. This is what battery QR codes point at.","description":"Content-negotiated. Always returns the public-tier projection (Part B legitimate-interest + Part C authorities-only fields stripped) regardless of unlock state, so QR scanners always resolve to a valid passport. Send `Accept: application/ld+json` for the JSON-LD; default returns a small JSON envelope pointing the browser at the localized viewer at https://batterycomply.com/p/{id}.","operationId":"v1_passport_resolve_api_v1_passport__passport_id__resolve_get","parameters":[{"name":"passport_id","in":"path","required":true,"schema":{"type":"string","title":"Passport Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/subscribe-guide":{"post":{"tags":["internal"],"summary":"Lead-magnet subscriber capture. Creates a MailerLite subscriber in the Field Guide Downloaders group, which fires the welcome-email automation.","operationId":"subscribe_guide_api_subscribe_guide_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuideSubscribeIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_analyze_api_analyze_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_analyze_api_analyze_post"},"Body_passport_build_api_passport_build_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_passport_build_api_passport_build_post"},"Body_v1_check_api_v1_check_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_v1_check_api_v1_check_post"},"Body_v1_passport_build_api_v1_passport_build_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_v1_passport_build_api_v1_passport_build_post"},"FeedbackIn":{"properties":{"message":{"type":"string","maxLength":4000,"minLength":1,"title":"Message"},"email":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}],"title":"Email"},"page_url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Page Url"},"report_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Report Id"}},"type":"object","required":["message"],"title":"FeedbackIn"},"GuideSubscribeIn":{"properties":{"email":{"type":"string","maxLength":320,"minLength":3,"title":"Email"},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Company"},"role":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Role"},"honeypot":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Honeypot"}},"type":"object","required":["email"],"title":"GuideSubscribeIn"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"v1: audit","description":"Compliance audit against EU 2023/1542 (10 checks)."},{"name":"v1: passport","description":"Digital Battery Passport build, fetch, and public QR resolver."},{"name":"internal","description":"Website-only endpoints. Not intended for third-party use; may break without notice."},{"name":"ops","description":"Health and uptime."}]}