{"openapi":"3.1.0","info":{"title":"Lead tools","description":"Send an API key in `X-API-Key: lt_...` (or `Authorization: Bearer lt_...`). Keys are created in the web page, *API keys* tab. Scope `read`: consult only; scope `full`: also start exports. Guide: [/developers](/developers).","version":"0.1.0"},"paths":{"/api/session":{"get":{"tags":["session"],"summary":"Is the web page logged in","operationId":"session_api_session_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/login":{"post":{"tags":["session"],"summary":"Log the web page in (admin password)","operationId":"login_api_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/logout":{"post":{"tags":["session"],"summary":"Log the web page out","operationId":"logout_api_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/health":{"get":{"tags":["account"],"summary":"State of the two connected services","description":"Checks the wizard key and the Data Center Pro key. Never fails: each service comes with `ok` true or false (and `error`).","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/remaining":{"get":{"tags":["remaining"],"summary":"Remaining leads to deliver per department","description":"From Data Center Pro, orders in progress: each order's remaining leads (ordered − delivered)\nare split equally between its departments; a department's `restant` is the sum of its shares.\nSorted from most to least. Same numbers as the admin's *Analyse de Couverture*, column *Total*.","operationId":"remaining_api_remaining_get","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"exact","in":"query","required":false,"schema":{"type":"boolean","description":"true = recomputed from the orders, without the 0.1 rounding","default":false,"title":"Exact"},"description":"true = recomputed from the orders, without the 0.1 rounding"},{"name":"type_lead","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"only this lead type (Data Center Pro ID)","title":"Type Lead"},"description":"only this lead type (Data Center Pro ID)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wizard/count":{"post":{"tags":["wizard"],"summary":"Numbers available in the wizard","description":"`depts` in free text: `13, 30`, `01-05`, `2A`, postal codes… `leads: true` counts leads instead of numbers. Changes nothing.","operationId":"wizard_count_api_wizard_count_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/wizard/lots":{"get":{"tags":["wizard"],"summary":"Latest wizard lots","description":"Most recent first (up to 500), with their files, whoever created them.","operationId":"wizard_lots_api_wizard_lots_get","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":25,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wizard/lots/{lot_id}/zip":{"get":{"tags":["wizard"],"summary":"Download a wizard lot (zip)","operationId":"wizard_lot_zip_api_wizard_lots__lot_id__zip_get","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"lot_id","in":"path","required":true,"schema":{"type":"integer","title":"Lot Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/plan":{"post":{"tags":["export"],"summary":"Preview an export (nothing is exported)","description":"Same parameters as `POST /api/jobs`. Returns the numbers without department (`sans`), per\ndepartment (`by_dept`) and the departments skipped under `min_per_dept` (`skipped`, with the\namount they would have had). Allowed to `read` keys.","operationId":"plan_api_plan_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/jobs":{"get":{"tags":["export"],"summary":"List exports","description":"Exports since the backend started, most recent first.","operationId":"list_jobs_api_jobs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]},"post":{"tags":["export"],"summary":"Start an export in the background","description":"Returns at once with the export (`id`, `status`). Follow it with `GET /api/jobs/{id}` until `status` is `done`, then download `GET /api/jobs/{id}/csv`. One export at a time (409). Scope `full`.","operationId":"create_job_api_jobs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuildIn"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/export":{"post":{"tags":["export"],"summary":"Export in one call (the CSV in the response)","description":"**One call, the CSV in the response.** Nothing to send: every parameter has a default.\n\nDepartments and their requests come from Data Center Pro (leads remaining to deliver). Each\ndepartment gets its request × `multiplier` numbers (departments under `min_per_dept` are\nskipped), plus `share_without_dept` of the total without department. The response is the\nfile `numero,departement` (`0` = without department).\n\nThe call lasts as long as the export (minutes for a big one): use a long timeout.\nIt shows up in the web page like any export.","operationId":"export_csv_api_export_post","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"multiplier","in":"query","required":false,"schema":{"type":"number","exclusiveMinimum":0,"description":"numbers per lead requested","default":200,"title":"Multiplier"},"description":"numbers per lead requested"},{"name":"share_without_dept","in":"query","required":false,"schema":{"type":"number","minimum":0,"exclusiveMaximum":1,"description":"share of the total without department","default":0.5,"title":"Share Without Dept"},"description":"share of the total without department"},{"name":"min_per_dept","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"skip departments under this","default":50,"title":"Min Per Dept"},"description":"skip departments under this"},{"name":"fmt","in":"query","required":false,"schema":{"enum":["brut","national","e164"],"type":"string","description":"national 0612…, brut 33612…, e164 +33612…","default":"national","title":"Fmt"},"description":"national 0612…, brut 33612…, e164 +33612…"},{"name":"mark","in":"query","required":false,"schema":{"type":"boolean","description":"true = real export, numbers marked as used","default":false,"title":"Mark"},"description":"true = real export, numbers marked as used"},{"name":"only_new","in":"query","required":false,"schema":{"type":"boolean","description":"leave out numbers already exported today","default":false,"title":"Only New"},"description":"leave out numbers already exported today"}],"responses":{"200":{"description":"numero,departement","content":{"text/csv":{}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}":{"get":{"tags":["export"],"summary":"Follow an export","description":"`status`: `queued`, `running`, `done` or `error`. `progress`: `{done, total, step}`. `log`: the messages. When done, `counts` per department (`0` = without department) and `csv`, the file name.","operationId":"get_job_api_jobs__job_id__get","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/csv":{"get":{"tags":["export"],"summary":"Download an export's CSV","description":"The build's single csv: numero,departement (0 = without department).","operationId":"job_csv_api_jobs__job_id__csv_get","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/me":{"get":{"tags":["account"],"summary":"Who am I","description":"Who is calling: the admin session or an API key (name and scope). A good first call.","operationId":"me_api_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/keys":{"get":{"tags":["keys"],"summary":"List API keys","operationId":"list_keys_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]},"post":{"tags":["keys"],"summary":"Create an API key","description":"Creates a key. The full key is in the response only: it is never shown again.","operationId":"create_key_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/keys/{key_id}/revoke":{"post":{"tags":["keys"],"summary":"Revoke an API key","operationId":"revoke_key_api_keys__key_id__revoke_post","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"BuildIn":{"properties":{"n_numbers":{"type":"integer","minimum":0.0,"title":"N Numbers","description":"total numbers (ignored when multiplier is set)","default":0},"leads_by_dept":{"additionalProperties":{"type":"number"},"type":"object","title":"Leads By Dept","description":"{department: leads requested}: the weights","examples":[{"77":450,"78":158.7,"91":312.7}]},"share_without_dept":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Share Without Dept","description":"share of the total without department","default":0.5},"multiplier":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Multiplier","description":"each department gets its leads × multiplier"},"min_per_dept":{"type":"integer","minimum":0.0,"title":"Min Per Dept","description":"skip departments that would get fewer numbers","default":0},"fmt":{"type":"string","enum":["brut","national","e164"],"title":"Fmt","description":"brut 33612…, national 0612…, e164 +33612…","default":"brut"},"mark":{"type":"boolean","title":"Mark","description":"true = real export: numbers marked as used in the wizard","default":false},"only_new":{"type":"boolean","title":"Only New","description":"leave out numbers already exported today, and top up","default":false},"name":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9_-]{1,60}$"},{"type":"null"}],"title":"Name","description":"file name (default lot_<date>_<time>)"}},"type":"object","required":["leads_by_dept"],"title":"BuildIn"},"CountIn":{"properties":{"depts":{"type":"string","minLength":1,"title":"Depts","description":"departments, free text","examples":["13, 30, 84"]},"leads":{"type":"boolean","title":"Leads","description":"count leads instead of numbers","default":false}},"type":"object","required":["depts"],"title":"CountIn"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"KeyIn":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name"},"scope":{"type":"string","enum":["read","full"],"title":"Scope","default":"read"}},"type":"object","required":["name"],"title":"KeyIn"},"LoginIn":{"properties":{"password":{"type":"string","title":"Password"}},"type":"object","required":["password"],"title":"LoginIn"},"PlanIn":{"properties":{"n_numbers":{"type":"integer","minimum":0.0,"title":"N Numbers","description":"total numbers (ignored when multiplier is set)","default":0},"leads_by_dept":{"additionalProperties":{"type":"number"},"type":"object","title":"Leads By Dept","description":"{department: leads requested}: the weights","examples":[{"77":450,"78":158.7,"91":312.7}]},"share_without_dept":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Share Without Dept","description":"share of the total without department","default":0.5},"multiplier":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Multiplier","description":"each department gets its leads × multiplier"},"min_per_dept":{"type":"integer","minimum":0.0,"title":"Min Per Dept","description":"skip departments that would get fewer numbers","default":0}},"type":"object","required":["leads_by_dept"],"title":"PlanIn"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","description":"API key created in the app (API keys tab)","in":"header","name":"X-API-Key"},"HTTPBearer":{"type":"http","description":"Same API key, as Authorization: Bearer lt_...","scheme":"bearer"}}},"tags":[{"name":"export","description":"Build the CSV `numero,departement`: in one call, or in the background."},{"name":"remaining","description":"Data Center Pro: leads remaining to deliver."},{"name":"wizard","description":"Wizard: availability and lots."},{"name":"account","description":"Check your key and the connected services."},{"name":"keys","description":"API keys of this app: web page (admin) only."},{"name":"session","description":"Login of the web page (public routes)."}]}