{"openapi":"3.1.0","info":{"title":"Multigest Protected API","description":"Multigest unified API for public and protected endpoints.","version":"1.0.0"},"paths":{"/public/listings/{listing_id}/photos":{"get":{"tags":["Listing Photos - Public"],"summary":"Get all photos for a specific listing","description":"Public endpoint - retrieves all vehicle photos associated with a given listing.","operationId":"get_listing_photos_public_listings__listing_id__photos_get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Listing ID","title":"Listing Id"},"description":"Listing ID"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Listing Photos Public Listings  Listing Id  Photos Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/listings/{listing_id}/equipments":{"get":{"tags":["Listing Equipments - Public"],"summary":"List equipment names for a specific listing","description":"Public endpoint — returns the list of equipment/features for a given listing.","operationId":"get_listing_equipments_public_listings__listing_id__equipments_get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Listing ID","title":"Listing Id"},"description":"Listing ID"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Listing Equipments Public Listings  Listing Id  Equipments Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/sales-person":{"get":{"tags":["Sales Person - Public"],"summary":"List sales team members for a website's company","description":"Public endpoint — retrieves all team members (salespeople) for the website's company.\nUses Teams → UserTeams → Utilizadores (same as lead attribution).\n\nOptional: ?include=trackingTeams to also return PV→team mappings from tracking numbers.","operationId":"list_sales_person_public_sales_person_get","parameters":[{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Include"}},{"name":"x-website-token","in":"header","required":false,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/listings":{"get":{"tags":["Listings - Public"],"summary":"List or filter listings (public site)","description":"Public endpoint for listings visible on client sites.","operationId":"get_public_listings_public_listings_get","parameters":[{"name":"brand","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Brand"}},{"name":"model","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Model"}},{"name":"fuel","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fuel"}},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Type"}},{"name":"seats","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seats"}},{"name":"transmission","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transmission"}},{"name":"pv","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pv"}},{"name":"section","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Integrazu section ID (e.g. 31=Cars, 32=Motorcycles)","title":"Section"},"description":"Integrazu section ID (e.g. 31=Cars, 32=Motorcycles)"},{"name":"ivaIncluded","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ivaincluded"}},{"name":"campaign","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Campaign"}},{"name":"minYear","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Minyear"}},{"name":"maxYear","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maxyear"}},{"name":"minPrice","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Minprice"}},{"name":"budget","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Budget"}},{"name":"minKm","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Minkm"}},{"name":"maxKm","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maxkm"}},{"name":"autonomia","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Autonomia"}},{"name":"maxAutonomia","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Maxautonomia"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","default":"price_asc","title":"Sort"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":48,"exclusiveMinimum":0,"default":12,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":0,"description":"Skip N items before pagination","default":0,"title":"Offset"},"description":"Skip N items before pagination"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Public Listings Public Listings Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/listings/{listing_id}":{"get":{"tags":["Listings - Public"],"summary":"Get a single listing by ID (public site)","operationId":"get_public_listing_by_id_public_listings__listing_id__get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Listing Id"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Public Listing By Id Public Listings  Listing Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/listings/campaigns/max-discount":{"get":{"tags":["Listings - Public"],"summary":"Get max campaign discount (public site)","operationId":"get_public_max_discount_public_listings_campaigns_max_discount_get","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Public Max Discount Public Listings Campaigns Max Discount Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/articles":{"get":{"tags":["Articles - Public"],"summary":"List all articles for a website","operationId":"list_articles_public_articles_get","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Article"},"title":"Response List Articles Public Articles Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/articles/{article_id}":{"get":{"tags":["Articles - Public"],"summary":"Get a single article","operationId":"get_article_public_articles__article_id__get","parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Article Id"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Article"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/banners":{"get":{"tags":["Banners - Public"],"summary":"List Banners for a Website","operationId":"list_banners_public_banners_get","parameters":[{"name":"service_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Optionally filter by service ID","title":"Service Id"},"description":"Optionally filter by service ID"},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","description":"Website domain token is required","title":"X-Website-Token"},"description":"Website domain token is required"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Banner"},"title":"Response List Banners Public Banners Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/reviews":{"get":{"tags":["Reviews - Public"],"summary":"List all reviews for a website","operationId":"list_reviews_public_reviews_get","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Reviews Public Reviews Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/reviews/{review_id}":{"get":{"tags":["Reviews - Public"],"summary":"Get a single review","operationId":"get_review_public_reviews__review_id__get","parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Review Id"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Review Public Reviews  Review Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/teams":{"get":{"tags":["Teams - Public"],"summary":"List all team members for a website","operationId":"list_team_public_teams_get","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Team Public Teams Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/teams/{member_id}":{"get":{"tags":["Teams - Public"],"summary":"Get a single team member","operationId":"get_member_public_teams__member_id__get","parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Member Id"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Member Public Teams  Member Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/makes":{"get":{"tags":["Makes - Public"],"summary":"List all makes for active listings in this site","description":"Returns all car makes that have active listings for the resolved website.\nWebsite ID is resolved from x-website-token header or authenticated user.","operationId":"get_makes_public_makes_get","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Makes Public Makes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/models":{"get":{"tags":["Models - Public"],"summary":"List models for a selected make","description":"Return all models available for the specified make (`brand`)\nand the resolved website (from user or x-website-token).","operationId":"get_models_by_make_public_models_get","parameters":[{"name":"brand","in":"query","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Brand"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Models By Make Public Models Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/filters/options":{"get":{"tags":["Filters - Public"],"summary":"All filter lookups & numeric ranges","description":"Returns available filter metadata (brands, models, fuel, type, etc.)\nalong with numeric range limits (price, year, km).","operationId":"get_all_filter_options_public_filters_options_get","parameters":[{"name":"make","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by make ID","title":"Make"},"description":"Filter by make ID"},{"name":"model","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by model ID","title":"Model"},"description":"Filter by model ID"},{"name":"section","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by section ID (e.g. 31=Cars)","title":"Section"},"description":"Filter by section ID (e.g. 31=Cars)"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get All Filter Options Public Filters Options Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/achievements":{"get":{"tags":["Achievements - Public"],"summary":"List all achievements for a website","description":"List visible achievements for a specific website.","operationId":"list_achievements_public_achievements_get","parameters":[{"name":"website","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"title":"Website"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Achievements Public Achievements Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/achievements/{achv_id}":{"get":{"tags":["Achievements - Public"],"summary":"Get a single achievement","description":"Fetch one achievement by ID (public view).","operationId":"get_achievement_public_achievements__achv_id__get","parameters":[{"name":"achv_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Achv Id"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Achievement Public Achievements  Achv Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/partners":{"get":{"tags":["Partners - Public"],"summary":"List all partners for a website","description":"List all partners for the given website.","operationId":"list_partners_public_partners_get","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Partners Public Partners Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/partners/{partner_id}":{"get":{"tags":["Partners - Public"],"summary":"Get a single partner by ID","description":"Get details of a specific partner.","operationId":"get_partner_public_partners__partner_id__get","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Partner Public Partners  Partner Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/contact-info":{"get":{"tags":["Contact Info - Public"],"summary":"Get contact information for the current website","description":"Public endpoint to retrieve a website's contact info.","operationId":"get_contact_info_public_contact_info_get","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Contact Info Public Contact Info Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/sitemap/info":{"get":{"tags":["Sitemap - Public"],"summary":"Get sitemap service info","description":"Returns basic information about the sitemap generator service.\nUseful for debugging or public docs.","operationId":"get_sitemap_info_public_sitemap_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/services":{"get":{"tags":["Services - Public"],"summary":"List linked website services","description":"Public — returns linked service list for a given website.","operationId":"get_website_service_links_public_services_get","parameters":[{"name":"show_in_nav","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by navigation visibility","title":"Show In Nav"},"description":"Filter by navigation visibility"},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort order","default":"nav_order","title":"Sort"},"description":"Sort order"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Website Service Links Public Services Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/service-types":{"get":{"tags":["Services - Public"],"summary":"List all available service types","description":"Public — returns all base service types.","operationId":"get_all_service_types_public_service_types_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Get All Service Types Public Service Types Get"}}}}}}},"/public/leads":{"post":{"tags":["Leads - Public"],"summary":"Submit a new lead","description":"Public endpoint for lead submission","operationId":"create_lead_public_leads_post","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_lead_public_leads_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/webhooks/meta/{team_token}":{"get":{"tags":["Leads - Public"],"summary":"Meta Webhook","operationId":"meta_webhook_public_webhooks_meta__team_token__get","parameters":[{"name":"team_token","in":"path","required":true,"schema":{"type":"string","title":"Team Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Leads - Public"],"summary":"Meta Webhook","operationId":"meta_webhook_public_webhooks_meta__team_token__get","parameters":[{"name":"team_token","in":"path","required":true,"schema":{"type":"string","title":"Team Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/webhooks/sibs":{"post":{"tags":["Webhooks - Public"],"summary":"Sibs Webhook","description":"Receives, decrypts, and processes webhooks from SIBS (MB WAY / Multibanco).\nThis endpoint is PUBLIC — called directly by SIBS systems.","operationId":"sibs_webhook_public_webhooks_sibs_post","parameters":[{"name":"X-Initialization-Vector","in":"header","required":true,"schema":{"type":"string","title":"X-Initialization-Vector"}},{"name":"X-Authentication-Tag","in":"header","required":true,"schema":{"type":"string","title":"X-Authentication-Tag"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/faturas":{"post":{"tags":["faturas-legacy"],"summary":"Legacy VBA invoice upload (public, no auth)","description":"Legacy VBA-compatible invoice upload endpoint.\n\nAccepts the exact payload format from the legacy VBA UploadInvoice function.\nNo authentication required - uses empresa/user_id/idpv from payload.\n\nURL: POST /public/faturas","operationId":"create_fatura_legacy_public_faturas_post","parameters":[{"name":"x-api-token","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_fatura_legacy_public_faturas_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Fatura Legacy Public Faturas Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/email/inbound":{"post":{"tags":["Email - Public"],"summary":"Inbound email webhook","description":"Receives inbound emails (from webhooks like AWS SES, SendGrid, etc.),\nparses them and stores attachments or metadata in the system.","operationId":"email_inbound_endpoint_public_email_inbound_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/email/inbox-ingest":{"post":{"tags":["Email - Public"],"summary":"Ingest .eml from Lambda (archive only)","description":"Archive-only ingest. Match recipient against `Z_Mailboxes`\n(Delivered-To → X-Original-To → To → Cc). If found → archive into\n`stand-gest:{co}/{pv}/emails/...` and insert a `Z_EmailMessages` row.\n\nNo mailbox match → RECORD the drop in `Z_EmailIngestDrops` and answer 202.\nPortal-lead emails (Standvirtual / OLX / Carmine / etc.) are owned by\nLambda's `BE_ENDPOINT` → `/email/inbound`, never this route.\n\nWhy 202 and not an error: the deployed SES Lambda's `_post_to_archive()`\nswallows every outcome and never raises, so a status code alone changes\nnothing observable — the durable row is the actual fix. And a 5xx would\nmake the second ingest Lambda retry a permanently unroutable address\nforever. 202 = \"accepted, not routed\", which is honest and terminal.","operationId":"email_inbox_ingest_public_email_inbox_ingest_post","parameters":[{"name":"X-Origin-Verify","in":"header","required":true,"schema":{"type":"string","title":"X-Origin-Verify"}},{"name":"X-Mailbox","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Mailbox"}},{"name":"X-SES-Bucket","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Ses-Bucket"}},{"name":"X-SES-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Ses-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/configs/{domain}":{"get":{"tags":["Configs - Public"],"summary":"Get all config file URLs","description":"Returns presigned URLs for all config files (tracking, header, body).","operationId":"get_all_configs_public_configs__domain__get","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/configs/tracking/{domain}":{"get":{"tags":["Configs - Public"],"summary":"Get tracking config URL","description":"Returns a presigned URL to the tracking JSON file.","operationId":"get_tracking_config_public_configs_tracking__domain__get","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/configs/header/{domain}":{"get":{"tags":["Configs - Public"],"summary":"Get page header HTML URL","description":"Returns a presigned URL to the header HTML file.","operationId":"get_page_header_public_configs_header__domain__get","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/configs/body/{domain}":{"get":{"tags":["Configs - Public"],"summary":"Get page body HTML URL","description":"Returns a presigned URL to the body HTML file.","operationId":"get_page_body_public_configs_body__domain__get","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/cookie/consent":{"post":{"tags":["Public Cookie Consent"],"summary":"Save Cookie Consent","operationId":"save_cookie_consent_public_cookie_consent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CookieConsentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CookieConsentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/cookie/status":{"get":{"tags":["Public Cookie Consent"],"summary":"Cookie Status","operationId":"cookie_status_public_cookie_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CookieConsentStatusResponse"}}}}}}},"/public/content":{"get":{"tags":["Websites - Public"],"summary":"Public Get Content","description":"Get published content pages for a website.\n\nQuery params:\n    - domain: Website domain (required)\n    - content_type: Content type slug to filter by (optional)\n    - limit: Max number of results (optional)\n\nReturns array of content items with parsed custom_meta.","operationId":"public_get_content_public_content_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"content_type","in":"query","required":false,"schema":{"type":"string","title":"Content Type"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/content/paginated":{"get":{"tags":["Websites - Public"],"summary":"Public Get Content Paginated","description":"Get paginated content with total count.\n\nQuery params:\n    - domain: Website domain (required)\n    - content_type: Content type slug to filter by (optional)\n    - page: Page number (default: 1)\n    - per_page: Items per page (default: 12)\n    - sort_by: Sort field - created_at, updated_at, title (default: created_at)\n    - sort_order: ASC or DESC (default: DESC)\n\nReturns:\n    {\n        \"items\": [...],\n        \"total\": 100,\n        \"page\": 1,\n        \"per_page\": 12,\n        \"total_pages\": 9\n    }","operationId":"public_get_content_paginated_public_content_paginated_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"content_type","in":"query","required":false,"schema":{"type":"string","title":"Content Type"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","default":12,"title":"Per Page"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","default":"created_at","title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","default":"DESC","title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/content/featured":{"get":{"tags":["Websites - Public"],"summary":"Public Get Featured Content","description":"Get featured/highlighted content (where custom_meta.destaque = true).\n\nQuery params:\n    - domain: Website domain (required)\n    - content_type: Content type slug to filter by (optional)\n    - limit: Max number of results (default: 6)","operationId":"public_get_featured_content_public_content_featured_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"content_type","in":"query","required":false,"schema":{"type":"string","title":"Content Type"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":6,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/content/recent":{"get":{"tags":["Websites - Public"],"summary":"Public Get Recent Content","description":"Get most recent content.\n\nQuery params:\n    - domain: Website domain (required)\n    - content_type: Content type slug to filter by (optional)\n    - limit: Max number of results (default: 6)\n    - exclude: Comma-separated list of page IDs to exclude (optional)","operationId":"public_get_recent_content_public_content_recent_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"content_type","in":"query","required":false,"schema":{"type":"string","title":"Content Type"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":6,"title":"Limit"}},{"name":"exclude","in":"query","required":false,"schema":{"type":"string","title":"Exclude"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/content/search":{"get":{"tags":["Websites - Public"],"summary":"Public Search Content","description":"Search content by title or custom_meta.\n\nQuery params:\n    - domain: Website domain (required)\n    - q: Search query (required)\n    - content_type: Content type slug to filter by (optional)\n    - limit: Max number of results (default: 20)","operationId":"public_search_content_public_content_search_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"q","in":"query","required":true,"schema":{"type":"string","title":"Q"}},{"name":"content_type","in":"query","required":false,"schema":{"type":"string","title":"Content Type"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/content/types":{"get":{"tags":["Websites - Public"],"summary":"Public Get Content Types","description":"Get all content types for a website.\nUseful for building navigation or filters.\n\nQuery params:\n    - domain: Website domain (required)\n\nReturns array of content types with counts.","operationId":"public_get_content_types_public_content_types_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/content/{content_type_slug}/{page_slug}":{"get":{"tags":["Websites - Public"],"summary":"Public Get Single Content","description":"Get a single content page by its content type and slug.\n\nURL format: /public/content/{content_type_slug}/{page_slug}\nExample: /public/content/campanhas/black-friday\n\nQuery params:\n    - domain: Website domain (required)","operationId":"public_get_single_content_public_content__content_type_slug___page_slug__get","parameters":[{"name":"content_type_slug","in":"path","required":true,"schema":{"type":"string","title":"Content Type Slug"}},{"name":"page_slug","in":"path","required":true,"schema":{"type":"string","title":"Page Slug"}},{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/website":{"get":{"tags":["Websites - Public"],"summary":"Public Get Website","operationId":"public_get_website_public_website_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/page":{"get":{"tags":["Websites - Public"],"summary":"Public Get Page","operationId":"public_get_page_public_page_get","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/pages":{"get":{"tags":["Websites - Public"],"summary":"Public Get All Pages","operationId":"public_get_all_pages_public_pages_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/websites/blocks":{"get":{"tags":["Websites - Public"],"summary":"Public Get Blocks","operationId":"public_get_blocks_public_websites_blocks_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/tracking/event":{"post":{"tags":["Tracking - Public"],"summary":"Track visitor event","description":"Track visitor event from frontend.\nUses background task for fire-and-forget performance.","operationId":"track_event_public_tracking_event_post","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackEventRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/tracking/events/batch":{"post":{"tags":["Tracking - Public"],"summary":"Track multiple events in batch","description":"Track multiple events in a single request (optimized for sendBeacon).\nFire-and-forget: returns 200 immediately, processes in background.","operationId":"track_events_batch_endpoint_public_tracking_events_batch_post","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","description":"Website domain","title":"Domain"},"description":"Website domain"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchEventsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/tracking/identify":{"post":{"tags":["Tracking - Public"],"summary":"Identify visitor","description":"Identify a visitor by linking visitor_id to email/name/phone.\n\nCalled when a visitor submits a form or provides their information.","operationId":"identify_visitor_public_tracking_identify_post","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentifyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/analytics/vehicles/{vehicle_id}/stats":{"get":{"tags":["Analytics - Public"],"summary":"Get vehicle statistics","description":"Get comprehensive statistics for a specific vehicle listing.\n\nReturns popularity metrics, engagement data, and conversion stats.\n\n**Args:**\n- vehicle_id: Vehicle ID from viatutaseasydatagreen table\n- domain: Website domain (query parameter)\n\n**Returns:**\n```json\n{\n  \"vehicle_id\": 665,\n  \"popularity\": {\n    \"view_count\": 156,\n    \"views_24h\": 47,\n    \"views_7d\": 203,\n    \"unique_visitors\": 89,\n    \"current_viewers\": 8,\n    \"trending_score\": 0.85\n  },\n  \"engagement\": {\n    \"avg_time_on_page\": 120,\n    \"scroll_completion_rate\": 0.65,\n    \"bounce_rate\": 0.32,\n    \"avg_scroll_depth\": 75\n  },\n  \"conversion\": {\n    \"lead_count\": 12,\n    \"leads_24h\": 3,\n    \"click_to_lead_rate\": 0.13\n  },\n  \"metadata\": {\n    \"last_viewed_at\": \"2025-12-21T14:30:00Z\",\n    \"is_trending\": true\n  }\n}\n```","operationId":"get_vehicle_statistics_public_analytics_vehicles__vehicle_id__stats_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"domain","in":"query","required":true,"schema":{"type":"string","description":"Website domain","title":"Domain"},"description":"Website domain"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/analytics/website/stats":{"get":{"tags":["Analytics - Public"],"summary":"Get global website statistics","description":"Get global website statistics.\n\nReturns total visits, page views, and leads for the entire website.\n\n**Args:**\n- domain: Website domain (query parameter)\n\n**Returns:**\n```json\n{\n  \"total_visits\": 1543,\n  \"total_page_views\": 8921,\n  \"total_leads\": 234\n}\n```\n\n**Metrics:**\n- `total_visits`: Total unique visitors to the website\n- `total_page_views`: Total page views across all pages\n- `total_leads`: Total leads generated for this website","operationId":"get_global_website_stats_public_analytics_website_stats_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","description":"Website domain","title":"Domain"},"description":"Website domain"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/analytics/page/stats":{"get":{"tags":["Analytics - Public"],"summary":"Get page analytics","description":"Get analytics for a specific page.\n\nReturns page views, unique visitors, and engagement metrics for any page.\n\n**Args:**\n- domain: Website domain (query parameter)\n- page_url: Page URL path (e.g., \"/viaturas\", \"/about\", \"/contact\")\n\n**Returns:**\n```json\n{\n  \"page_url\": \"/viaturas\",\n  \"total_views\": 2341,\n  \"unique_visitors\": 1823,\n  \"views_24h\": 156,\n  \"views_7d\": 892,\n  \"avg_time_on_page\": 145,\n  \"bounce_rate\": 0.42,\n  \"last_viewed_at\": \"2025-12-21T14:30:00Z\"\n}\n```\n\n**Metrics:**\n- `page_url`: The page URL\n- `total_views`: Total page views (all time)\n- `unique_visitors`: Unique visitors to this page\n- `views_24h`: Views in last 24 hours\n- `views_7d`: Views in last 7 days\n- `avg_time_on_page`: Average seconds on page\n- `bounce_rate`: Bounce rate (0.0 - 1.0)\n- `last_viewed_at`: Last view timestamp","operationId":"get_page_analytics_public_analytics_page_stats_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","description":"Website domain","title":"Domain"},"description":"Website domain"},{"name":"page_url","in":"query","required":true,"schema":{"type":"string","description":"Page URL (e.g., /viaturas, /about, /contact)","title":"Page Url"},"description":"Page URL (e.g., /viaturas, /about, /contact)"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/invitations/validate/{token}":{"get":{"tags":["Invitations - Public"],"summary":"Validate an invitation token","description":"Validates an invitation token and returns invitation details.\nUsed by frontend to display company name before signup.","operationId":"validate_invitation_public_invitations_validate__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","minLength":1,"title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Validate Invitation Public Invitations Validate  Token  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/pontos-venda/":{"get":{"tags":["pontos-venda-public"],"summary":"List Pontos Venda","description":"List all points of sale for the company associated with the website token.\n\nReturns paginated list with address, email, and photo info.","operationId":"list_pontos_venda_public_pontos_venda__get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Items to skip","default":0,"title":"Skip"},"description":"Items to skip"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Items per page","default":100,"title":"Limit"},"description":"Items per page"},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PontoVendaListResponseWrapper"}}}},"404":{"description":"Not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/pontos-venda/{pv_id}":{"get":{"tags":["pontos-venda-public"],"summary":"Get Ponto Venda","description":"Get details for a specific point of sale.\nRequires x-website-token — PV must belong to the token's company.","operationId":"get_ponto_venda_public_pontos_venda__pv_id__get","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PontoVendaResponse"}}}},"404":{"description":"Not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/pontos-venda/{pv_id}/addresses":{"get":{"tags":["pontos-venda-public"],"summary":"Get Pv Addresses","description":"Get all addresses for a point of sale. Requires x-website-token.","operationId":"get_pv_addresses_public_pontos_venda__pv_id__addresses_get","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnderecoResponse"},"title":"Response Get Pv Addresses Public Pontos Venda  Pv Id  Addresses Get"}}}},"404":{"description":"Not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/pontos-venda/{pv_id}/emails":{"get":{"tags":["pontos-venda-public"],"summary":"Get Pv Emails","description":"Get all emails for a point of sale. Requires x-website-token.","operationId":"get_pv_emails_public_pontos_venda__pv_id__emails_get","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailResponse"},"title":"Response Get Pv Emails Public Pontos Venda  Pv Id  Emails Get"}}}},"404":{"description":"Not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/webhooks/telnyx/texml":{"post":{"tags":["Webhooks - Telnyx"],"summary":"Handle Texml Incoming","description":"TeXML endpoint for incoming calls.\nReturns XML with <Say> for GDPR notice and <Dial> for routing.\n\nRouting logic:\n- If caller has an existing lead with assigned user in team:\n  Direct route to that user (15s timeout), fallback to full team.\n- Otherwise: ring all team members simultaneously (30s timeout).","operationId":"handle_texml_incoming_public_webhooks_telnyx_texml_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/webhooks/telnyx/texml/number-answered":{"post":{"tags":["Webhooks - Telnyx"],"summary":"Handle Texml Number Answered","description":"TeXML <Number url> callback — fires when a team member answers, BEFORE bridging.\nRecords who answered so we have it even if caller hangs up first\n(which prevents dial-complete from firing).\nReturns empty <Response/> to proceed with bridging immediately.","operationId":"handle_texml_number_answered_public_webhooks_telnyx_texml_number_answered_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/webhooks/telnyx/texml/dial-complete":{"post":{"tags":["Webhooks - Telnyx"],"summary":"Handle Texml Dial Complete","description":"TeXML action callback when dial completes.\n\nTwo paths:\n1. Direct routing no-answer → return fallback XML to ring all team members\n2. Normal completion → handle answered_by, billing, lead history","operationId":"handle_texml_dial_complete_public_webhooks_telnyx_texml_dial_complete_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/webhooks/telnyx/texml/status":{"post":{"tags":["Webhooks - Telnyx"],"summary":"Handle Texml Status","description":"TeXML call progress/status callback.\nUpdates call status based on call progress events.\nHandles lead creation, attribution, and SMS alerts.","operationId":"handle_texml_status_public_webhooks_telnyx_texml_status_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/webhooks/telnyx/texml/recording":{"post":{"tags":["Webhooks - Telnyx"],"summary":"Handle Texml Recording","description":"TeXML recording status callback.\nSaves recording URL to call record.\nAlso updates call status to 'completed' as fallback (recording = call was answered).","operationId":"handle_texml_recording_public_webhooks_telnyx_texml_recording_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/webhooks/telnyx/orders":{"post":{"tags":["Webhooks - Telnyx"],"summary":"Handle Number Order Status","description":"Telnyx webhook for number_order.status_changed events.\n\nFinalises or discards the pending stub created when /call-tracking/numbers\nwas hit with an async-resolving order. Credits are charged here (not at\nrequest time) so nothing is billed until Telnyx confirms provisioning.\n\nTelnyx retries on non-2xx, so errors inside handlers log-and-return 200\nfor anything we've already processed idempotently.","operationId":"handle_number_order_status_public_webhooks_telnyx_orders_post","parameters":[{"name":"telnyx-signature-ed25519","in":"header","required":false,"schema":{"type":"string","title":"Telnyx-Signature-Ed25519"}},{"name":"telnyx-timestamp","in":"header","required":false,"schema":{"type":"string","title":"Telnyx-Timestamp"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/webhooks/telnyx/health":{"get":{"tags":["Webhooks - Telnyx"],"summary":"Telnyx Webhook Health","description":"Health check for Telnyx webhook endpoint.","operationId":"telnyx_webhook_health_public_webhooks_telnyx_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/attendance/qr":{"get":{"tags":["Attendance Public"],"summary":"Get QR code via API token (no login)","description":"Public endpoint for displaying the attendance QR code on a tablet/screen.\nAuthenticates via x-api-token header (company API token).\nNo user login required — designed for shared devices at the workplace.","operationId":"api_public_qr_public_attendance_qr_get","parameters":[{"name":"idpointofsale","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Optional POS scope","title":"Idpointofsale"},"description":"Optional POS scope"},{"name":"x-api-token","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/attendance/qr/link":{"get":{"tags":["Attendance Public"],"summary":"Get QR code via query param token (for bookmarkable links)","description":"Same as /attendance/qr but accepts token as query parameter.\nDesigned for bookmarkable URLs that can be opened on any browser/tablet:\nhttps://api.domain.com/public/attendance/qr/link?token=YOUR_TOKEN&idpointofsale=1","operationId":"api_public_qr_link_public_attendance_qr_link_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","description":"Company API token","title":"Token"},"description":"Company API token"},{"name":"idpointofsale","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Optional POS scope","title":"Idpointofsale"},"description":"Optional POS scope"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/attendance/link/{link_token}":{"get":{"tags":["Attendance Public"],"summary":"Get QR code via attendance link (no login)","description":"Public endpoint for tablet/screen QR display using a dedicated attendance link.\nNo login or API token needed — just open the URL with the link token.\n\nExample: https://api.domain.com/public/attendance/link/abc123random","operationId":"api_public_qr_via_link_public_attendance_link__link_token__get","parameters":[{"name":"link_token","in":"path","required":true,"schema":{"type":"string","title":"Link Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/ai-pricing":{"get":{"tags":["AI Pricer"],"summary":"Public Ai Pricing","description":"Client-facing vehicle pricing.\nRequires at least email OR phone.","operationId":"public_ai_pricing_public_ai_pricing_get","parameters":[{"name":"marca","in":"query","required":true,"schema":{"type":"string","title":"Marca"}},{"name":"modelo","in":"query","required":true,"schema":{"type":"string","title":"Modelo"}},{"name":"kms","in":"query","required":true,"schema":{"type":"integer","title":"Kms"}},{"name":"year","in":"query","required":true,"schema":{"type":"integer","title":"Year"}},{"name":"fuel","in":"query","required":true,"schema":{"type":"string","title":"Fuel"}},{"name":"email","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},{"name":"phone","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"}},{"name":"version","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version"}},{"name":"doors","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Doors"}},{"name":"engine_capacity","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Engine Capacity"}},{"name":"power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Power"}},{"name":"gearbox","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gearbox"}},{"name":"vehicle_type","in":"query","required":false,"schema":{"enum":["car","moto","comercial","pesado"],"type":"string","description":"Vehicle category — picks scraper section + AI prompt variant","default":"car","title":"Vehicle Type"},"description":"Vehicle category — picks scraper section + AI prompt variant"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["AI Pricer"],"summary":"Public Ai Pricing With Lead","description":"Single endpoint: runs appraisal, saves history, creates/updates lead, links them.\nBody: { marca, modelo, kms, year, fuel, email, phone, name, version?, doors?,\n        engine_capacity?, power?, gearbox?, team_id?, fromurl?, message? }","operationId":"public_ai_pricing_with_lead_public_ai_pricing_post","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/brands":{"get":{"tags":["Vehicles Data - Public"],"summary":"Public Get Brands","description":"Get vehicle brands for cars (section 31) — public, deduplicated.","operationId":"public_get_brands_public_vehicles_data_brands_get","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/models/{brand_id}":{"get":{"tags":["Vehicles Data - Public"],"summary":"Public Get Models","description":"Get models for a specific brand (public).","operationId":"public_get_models_public_vehicles_data_models__brand_id__get","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"integer","title":"Brand Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/fuel-types":{"get":{"tags":["Vehicles Data - Public"],"summary":"Public Get Fuel Types","description":"Get all fuel types (public).","operationId":"public_get_fuel_types_public_vehicles_data_fuel_types_get","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FuelTypeComboItem"},"title":"Response Public Get Fuel Types Public Vehicles Data Fuel Types Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/gearbox-types":{"get":{"tags":["Vehicles Data - Public"],"summary":"Public Get Gearbox Types","description":"Get all gearbox types (public).","operationId":"public_get_gearbox_types_public_vehicles_data_gearbox_types_get","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GearboxComboItem"},"title":"Response Public Get Gearbox Types Public Vehicles Data Gearbox Types Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/sections":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Sections","description":"List Integrazu sections the public appraisal widget supports.","operationId":"public_get_sections_public_vehicles_data_catalog_sections_get","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Sections Public Vehicles Data Catalog Sections Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/brands":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Brands","description":"Get vehicle brands for a section. Defaults to Carros (31) when neither param is provided.","operationId":"public_get_brands_public_vehicles_data_catalog_brands_get","parameters":[{"name":"section_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Integrazu section ID (preferred)","title":"Section Id"},"description":"Integrazu section ID (preferred)"},{"name":"vehicle_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Legacy: car|moto|comercial|pesado — resolved to section_id","title":"Vehicle Type"},"description":"Legacy: car|moto|comercial|pesado — resolved to section_id"},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Brands Public Vehicles Data Catalog Brands Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/models/{brand_id}":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Models","description":"Get models for a specific brand (public).","operationId":"public_get_models_public_vehicles_data_catalog_models__brand_id__get","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"integer","title":"Brand Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Models Public Vehicles Data Catalog Models  Brand Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/fuels/{model_id}":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Fuels","description":"Get fuel types for a specific model (public). is_imported_car defaults to 0.","operationId":"public_get_fuels_public_vehicles_data_catalog_fuels__model_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Fuels Public Vehicles Data Catalog Fuels  Model Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/engine-powers/{model_id}/{fuel_id}":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Engine Powers","description":"Get engine power options for model and fuel (public).","operationId":"public_get_engine_powers_public_vehicles_data_catalog_engine_powers__model_id___fuel_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Engine Powers Public Vehicles Data Catalog Engine Powers  Model Id   Fuel Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/engine-capacities/{model_id}/{fuel_id}":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Engine Capacities","description":"Get engine capacity options filtered by model, fuel, year, and power (public).","operationId":"public_get_engine_capacities_public_vehicles_data_catalog_engine_capacities__model_id___fuel_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"engine_power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine power in HP","title":"Engine Power"},"description":"Engine power in HP"},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Engine Capacities Public Vehicles Data Catalog Engine Capacities  Model Id   Fuel Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/doors/{model_id}/{fuel_id}":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Doors","description":"Get door count options filtered by specs (public).","operationId":"public_get_doors_public_vehicles_data_catalog_doors__model_id___fuel_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"engine_power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine power in HP","title":"Engine Power"},"description":"Engine power in HP"},{"name":"engine_capacity","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine capacity in cc","title":"Engine Capacity"},"description":"Engine capacity in cc"},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Doors Public Vehicles Data Catalog Doors  Model Id   Fuel Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/gearboxes/{model_id}/{fuel_id}":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Gearboxes","description":"Get gearbox options filtered by all previous selections (public).","operationId":"public_get_gearboxes_public_vehicles_data_catalog_gearboxes__model_id___fuel_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"engine_power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine power in HP","title":"Engine Power"},"description":"Engine power in HP"},{"name":"engine_capacity","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine capacity in cc","title":"Engine Capacity"},"description":"Engine capacity in cc"},{"name":"door_count","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Number of doors","title":"Door Count"},"description":"Number of doors"},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Gearboxes Public Vehicles Data Catalog Gearboxes  Model Id   Fuel Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/versions/{model_id}":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Versions Flat","description":"Get all versions/trims for a model (public, model-only).\n\nThe catalog cascade (/versions/{model_id}/{fuel_id}/{gearbox_id}) has no\nfuel/gearbox coverage for non-car sections (Comerciais/Motos/Pesados), so\nthe website widget can't reach a version that way. This flat endpoint\nmirrors the protected /versions/{model_id} and returns the full version\nlist straight off the model id.","operationId":"public_get_versions_flat_public_vehicles_data_catalog_versions__model_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Versions Flat Public Vehicles Data Catalog Versions  Model Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/vehicles/data/catalog/versions/{model_id}/{fuel_id}/{gearbox_id}":{"get":{"tags":["Vehicles Data Catalog - Public"],"summary":"Public Get Versions","description":"Get vehicle versions filtered by specs (public).","operationId":"public_get_versions_public_vehicles_data_catalog_versions__model_id___fuel_id___gearbox_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"gearbox_id","in":"path","required":true,"schema":{"type":"integer","title":"Gearbox Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"engine_power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine power in HP","title":"Engine Power"},"description":"Engine power in HP"},{"name":"engine_capacity","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine capacity in cc","title":"Engine Capacity"},"description":"Engine capacity in cc"},{"name":"door_count","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Number of doors","title":"Door Count"},"description":"Number of doors"},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Public Get Versions Public Vehicles Data Catalog Versions  Model Id   Fuel Id   Gearbox Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/marketing/track/open/{tracking_id}":{"get":{"tags":["Marketing Public"],"summary":"Track Open","description":"Open tracking endpoint. Returns 1x1 transparent GIF.\nCalled when email client loads the tracking pixel.","operationId":"track_open_public_marketing_track_open__tracking_id__get","parameters":[{"name":"tracking_id","in":"path","required":true,"schema":{"type":"string","title":"Tracking Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/marketing/unsubscribe/{tracking_id}":{"get":{"tags":["Marketing Public"],"summary":"Public Unsubscribe Page","description":"Public unsubscribe confirmation page.","operationId":"public_unsubscribe_page_public_marketing_unsubscribe__tracking_id__get","parameters":[{"name":"tracking_id","in":"path","required":true,"schema":{"type":"string","title":"Tracking Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Marketing Public"],"summary":"Confirm Unsubscribe","description":"Confirm unsubscribe action.","operationId":"confirm_unsubscribe_public_marketing_unsubscribe__tracking_id__post","parameters":[{"name":"tracking_id","in":"path","required":true,"schema":{"type":"string","title":"Tracking Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/meta/{domain}/catalog.xml":{"get":{"tags":["Meta Catalog - Public"],"summary":"Meta/Google product catalog feed (XML)","description":"Return one brand's vehicle catalog as a Google-Merchant RSS feed.\nThe ``domain`` resolves the **brand** scope (404 if unknown), so the feed\nonly contains that brand's stock — never a sibling brand's. ``?portal=``\noptionally narrows the destination.","operationId":"get_meta_catalog_public_meta__domain__catalog_xml_get","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","minLength":3,"description":"Public website domain of the dealer","title":"Domain"},"description":"Public website domain of the dealer"},{"name":"portal","in":"query","required":false,"schema":{"type":"string","description":"Destination slug, or 'site' for website-only","title":"Portal"},"description":"Destination slug, or 'site' for website-only"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/meta/{domain}/vehicles.xml":{"get":{"tags":["Meta Catalog - Public"],"summary":"Meta Automotive Inventory Ads (vehicle) catalog feed (XML)","description":"One brand's catalog in Meta's **vehicle (AIA)** format — the correct type for\na \"Veículos\" catalog (vs the Google-Merchant /catalog.xml used for \"produtos\nfísicos\"). Brand-scoped by ``domain`` (404 if unknown).","operationId":"get_meta_vehicle_feed_public_meta__domain__vehicles_xml_get","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","minLength":3,"description":"Public website domain of the dealer","title":"Domain"},"description":"Public website domain of the dealer"},{"name":"portal","in":"query","required":false,"schema":{"type":"string","description":"Destination slug, or 'site' for website-only","title":"Portal"},"description":"Destination slug, or 'site' for website-only"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/redirect-links/resolve":{"get":{"tags":["Redirect Links - Public"],"summary":"Public Resolve Redirect","description":"Resolve a redirect link slug for a given domain.\nReturns the target URL with UTM parameters appended.\nAtomically increments click_count.","operationId":"public_resolve_redirect_public_redirect_links_resolve_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","description":"Website domain","title":"Domain"},"description":"Website domain"},{"name":"slug","in":"query","required":true,"schema":{"type":"string","description":"Redirect link slug","title":"Slug"},"description":"Redirect link slug"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/register":{"post":{"tags":["Company Registration - Public"],"summary":"Register a new company","description":"Public endpoint for company registration.\nAccepts multipart/form-data with a CAE document.\nCreates a registration record for admin review.","operationId":"register_company_public_register_post","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_register_company_public_register_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/onboarding-questionnaire/{token}":{"get":{"tags":["Onboarding Questionnaire - Public"],"summary":"Load a questionnaire by its link token (no login)","operationId":"get_questionnaire_public_onboarding_questionnaire__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/onboarding-questionnaire/{token}/sections/{section_key}":{"put":{"tags":["Onboarding Questionnaire - Public"],"summary":"Save one section (autosave)","operationId":"save_section_public_onboarding_questionnaire__token__sections__section_key__put","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"section_key","in":"path","required":true,"schema":{"type":"string","title":"Section Key"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/onboarding-questionnaire/{token}/uploads/{kind}":{"post":{"tags":["Onboarding Questionnaire - Public"],"summary":"Upload the logo or the filled stock workbook","operationId":"upload_file_public_onboarding_questionnaire__token__uploads__kind__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","description":"Link token","title":"Token"},"description":"Link token"},{"name":"kind","in":"path","required":true,"schema":{"type":"string","description":"logo | stock_excel","title":"Kind"},"description":"logo | stock_excel"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_file_public_onboarding_questionnaire__token__uploads__kind__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/onboarding-questionnaire/{token}/stock-template":{"get":{"tags":["Onboarding Questionnaire - Public"],"summary":"Download the vehicle-import Excel template","description":"Redirect to a short-lived presigned URL for the pre-built workbook.\n\nThe workbook is generated once, when the link is issued. Building it per\nrequest would put ~12 reference queries, a full brand/model catalogue load\nand an openpyxl render behind an anonymous endpoint — the single most\nexpensive thing on the public surface, on a memory-bound host.","operationId":"download_stock_template_public_onboarding_questionnaire__token__stock_template_get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/onboarding-questionnaire/{token}/submit":{"post":{"tags":["Onboarding Questionnaire - Public"],"summary":"Submit the questionnaire","operationId":"submit_questionnaire_public_onboarding_questionnaire__token__submit_post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/email/unsubscribe":{"get":{"tags":["Email Opt-out"],"summary":"Unsubscribe","operationId":"unsubscribe_public_email_unsubscribe_get","parameters":[{"name":"e","in":"query","required":true,"schema":{"type":"string","title":"E"}},{"name":"t","in":"query","required":true,"schema":{"type":"string","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/webhooks/ses/events":{"post":{"tags":["Webhooks SES"],"summary":"Ses Events","operationId":"ses_events_public_webhooks_ses_events_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/vehicles/{vehicle_id}/photos":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Vehicle Photos","description":"Get all photos for a vehicle.\n\nReturns list of photos with url and sort_order from localizacaofotos table.","operationId":"get_vehicle_photos_api_vehicles__vehicle_id__photos_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Vehicles (Protected)"],"summary":"Upload Vehicle Photos","description":"Upload photos for a vehicle.\n\n- Uploads images to S3 bucket under {company_name}/{vehicle_id}/ prefix\n- Saves photo records to Localizacaofotos table\n- First photo (ordem=1) is set as main photo on Viatura.bucketurl\n\nArgs:\n    vehicle_id: Vehicle ID\n    files: List of image files to upload\n    replace_existing: If True, deletes all existing photos before upload","operationId":"upload_vehicle_photos_api_vehicles__vehicle_id__photos_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_vehicle_photos_api_vehicles__vehicle_id__photos_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Vehicles (Protected)"],"summary":"Delete Vehicle Photo Endpoint","description":"Delete a specific photo from a vehicle.\n\nArgs:\n    vehicle_id: Vehicle ID\n    url: Full URL of the photo to delete","operationId":"delete_vehicle_photo_endpoint_api_vehicles__vehicle_id__photos_delete","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"url","in":"query","required":true,"schema":{"type":"string","description":"Photo URL to delete","title":"Url"},"description":"Photo URL to delete"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/photos/download":{"get":{"tags":["Vehicle Photos - Admin"],"summary":"Download all vehicle photos as a ZIP file","description":"Fetches all photos for a vehicle from S3 and returns them as a ZIP archive.","operationId":"download_vehicle_photos_zip_api_vehicles__vehicle_id__photos_download_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Vehicle Id"}},{"name":"license_plate","in":"query","required":false,"schema":{"type":"string","default":"viatura","title":"License Plate"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/photos/sync/{job_id}":{"get":{"tags":["Vehicle Photos - Admin"],"summary":"Get Integrazu sync job status","description":"Poll this endpoint to get Integrazu sync progress.\n\nStatus values:\n- pending: Job created, not started yet\n- processing: Sync in progress\n- completed: All done (check adverts_synced vs adverts_failed)\n- failed: Fatal error occurred\n\nFrontend should poll every 1-2 seconds until status is 'completed' or 'failed'.","operationId":"get_sync_job_status_api_vehicles__vehicle_id__photos_sync__job_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Vehicle Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string","description":"Sync job ID","title":"Job Id"},"description":"Sync job ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncJobStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/photos/sync":{"post":{"tags":["Vehicle Photos - Admin"],"summary":"Force sync vehicle photos to Integrazu adverts","description":"Force sync: Push all LocalizacaoFotos images to all Integrazu adverts.\n\nValidates ownership synchronously, then dispatches the Integrazu sync via\nRedis queue (or thread fallback if Redis is unreachable). Frontend polls\nGET /vehicles/{id}/photos/sync/{job_id} for status.","operationId":"force_sync_vehicle_photos_api_vehicles__vehicle_id__photos_sync_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Force Sync Vehicle Photos Api Vehicles  Vehicle Id  Photos Sync Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/{listing_id}":{"get":{"tags":["Listings - Admin"],"summary":"Get a single listing by ID with exports","description":"Get a single listing by ID from ViaturasEasyDataGreen.\n\nAutomatically fetches Integrazu advert data for ALL configured brands\nwith platform publication statuses. Also includes website export data.\n\nArgs:\n    listing_id: ViaturasEasyDataGreen.ID\n\nReturns:\n    {\n        \"listing\": { ... ViaturasEasyDataGreen data ... },\n        \"integrazu\": {\n            \"status\": \"published\" | \"not_published\" | \"not_configured\" | \"no_pv\",\n            \"brands\": [\n                {\n                    \"brand_id\": 1,\n                    \"status\": \"published\" | \"not_published\" | \"no_token\" | \"error\",\n                    \"renew\": false,\n                    \"advert_id\": 34326,\n                    \"platforms\": [\n                        {\n                            \"platform\": \"carmine\",\n                            \"designation\": \"Carmine\",\n                            \"logo\": \"https://...\",\n                            \"advert_id\": \"1601032\",\n                            \"status\": \"Ativo\",\n                            \"url\": null\n                        }\n                    ]\n                }\n            ]\n        },\n        \"website_exports\": [\n            {\"id\": 1, \"id_ad\": 925, \"id_website\": 5, \"website_domain\": \"stand.pt\"},\n            ...\n        ]\n    }","operationId":"get_single_listing_api_listings__listing_id__get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Listing Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Single Listing Api Listings  Listing Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Listings - Admin"],"summary":"Update an existing listing (backoffice)","operationId":"update_existing_listing_api_listings__listing_id__put","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Listing Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Existing Listing Api Listings  Listing Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Listings - Admin"],"summary":"Delete a listing (backoffice)","operationId":"delete_existing_listing_api_listings__listing_id__delete","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Listing Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Existing Listing Api Listings  Listing Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings":{"post":{"tags":["Listings - Admin"],"summary":"Create a new listing (backoffice)","operationId":"create_new_listing_api_listings_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create New Listing Api Listings Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/save":{"post":{"tags":["Listings - Admin"],"summary":"Create or update listing with smart Integrazu integration","description":"Unified save endpoint that:\n1. IF listing_id is null: Creates new listing in ViaturasEasyDataGreen\n   IF listing_id is provided: Updates existing listing\n2. IF brands with platforms are provided:\n   - Checks existing Integrazu state\n   - Decides whether to start a job or send direct update\n3. IF website_ids are provided:\n   - Creates Z_WebsiteExports records\n\nDecision Logic for Integrazu:\n- No advert exists -> Start job (create + photos + publish)\n- Advert exists + new platforms -> Start job (publish only)\n- Advert exists + all platforms synced -> Direct PUT update (no job)\n\nArgs:\n    request_body: ListingSaveRequest with listing_id (optional), listing_data, brands, website_ids, image_urls\n\nReturns:\n    ListingSaveResponse with results per brand","operationId":"save_listing_with_integrazu_export_api_listings_save_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSaveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSaveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/{listing_id}/unpublish-all":{"post":{"tags":["Listings - Admin"],"summary":"Unpublish listing from all portals and websites","description":"Remove a listing from all Integrazu portals and websites.\n\nThis endpoint:\n1. Verifies listing ownership (company isolation)\n2. Deletes all Integrazu adverts via _handle_unpublish_all\n3. Removes all Z_WebsiteExports records for the listing\n\nArgs:\n    listing_id: ViaturasEasyDataGreen.ID","operationId":"unpublish_listing_from_all_api_listings__listing_id__unpublish_all_post","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Listing Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unpublish Listing From All Api Listings  Listing Id  Unpublish All Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/unpublish-all/by-vehicle/{vehicle_id}":{"post":{"tags":["Listings - Admin"],"summary":"Unpublish listing from all portals and websites (by vehicle ID)","description":"Same as /listings/{listing_id}/unpublish-all but resolves listing from vehicle ID.\nUseful when the caller only has the Viatura.ID (e.g., ContractDialog).","operationId":"unpublish_listing_by_vehicle_api_listings_unpublish_all_by_vehicle__vehicle_id__post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unpublish Listing By Vehicle Api Listings Unpublish All By Vehicle  Vehicle Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/by-vehicle/prefill/{vehicle_id}":{"get":{"tags":["Listings - Admin"],"summary":"Get prefill data for new listing from vehicle","description":"Get pre-fill data for creating a new listing from an existing vehicle.\n\nMaps Viatura table fields to ViaturasEasyDataGreen format so the frontend\ncan pre-populate the listing creation form.\n\nArgs:\n    vehicle_id: Viatura.ID\n\nReturns:\n    Dict with ViaturasEasyDataGreen field names populated from Viatura data","operationId":"get_listing_prefill_from_vehicle_api_listings_by_vehicle_prefill__vehicle_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Listing Prefill From Vehicle Api Listings By Vehicle Prefill  Vehicle Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/by-vehicle/{vehicle_id}":{"get":{"tags":["Listings - Admin"],"summary":"Get listing ID by vehicle ID","description":"Get the listing ID for a vehicle.\n\nArgs:\n    vehicle_id: Viatura.ID\n\nReturns:\n    {\"vehicle_id\": 123, \"listing_id\": 456} or {\"vehicle_id\": 123, \"listing_id\": null}","operationId":"get_listing_by_vehicle_id_api_listings_by_vehicle__vehicle_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Listing By Vehicle Id Api Listings By Vehicle  Vehicle Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/{listing_id}/website-exports":{"get":{"tags":["Listings - Admin"],"summary":"Get website exports for a listing","description":"Get all websites a listing is exported to.\n\nArgs:\n    listing_id: ViaturasEasyDataGreen.ID\n\nReturns:\n    List of Z_WebsiteExports records with website domain","operationId":"get_listing_website_exports_api_listings__listing_id__website_exports_get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Listing Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Listing Website Exports Api Listings  Listing Id  Website Exports Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/{listing_id}/website-export":{"post":{"tags":["Listings - Admin"],"summary":"Publish listing to a website","description":"Publish a listing to a website (create Z_WebsiteExports record).\n\nArgs:\n    listing_id: ViaturasEasyDataGreen.ID\n    website_id: Websites.id to publish to","operationId":"publish_listing_to_website_api_listings__listing_id__website_export_post","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Listing Id"}},{"name":"website_id","in":"query","required":true,"schema":{"type":"integer","description":"Websites.id to publish to","title":"Website Id"},"description":"Websites.id to publish to"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Publish Listing To Website Api Listings  Listing Id  Website Export Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Listings - Admin"],"summary":"Unpublish listing from a website","description":"Unpublish a listing from a website (delete Z_WebsiteExports record).\n\nArgs:\n    listing_id: ViaturasEasyDataGreen.ID\n    website_id: Websites.id to unpublish from","operationId":"unpublish_listing_from_website_api_listings__listing_id__website_export_delete","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Listing Id"}},{"name":"website_id","in":"query","required":true,"schema":{"type":"integer","description":"Websites.id to unpublish from","title":"Website Id"},"description":"Websites.id to unpublish from"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unpublish Listing From Website Api Listings  Listing Id  Website Export Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/{listing_id}/integrazu-exports":{"get":{"tags":["Listings - Admin"],"summary":"Get Integrazu exports for a listing with platform statuses","description":"Get all portal exports for a listing, enriched with Integrazu platform statuses.\n\nFor each brand that has a Z_PortalExports record for this listing,\nfetches the advert from Integrazu API to get platform publication statuses.\n\nArgs:\n    listing_id: ViaturasEasyDataGreen.ID\n\nReturns:\n    {\n        \"listing_id\": 925,\n        \"pv_id\": 9,\n        \"integrazu\": {\n            \"status\": \"published\" | \"not_published\" | \"not_configured\" | \"no_pv\",\n            \"brands\": [\n                {\n                    \"brand_id\": 1,\n                    \"status\": \"published\" | \"not_published\" | \"no_token\" | \"error\",\n                    \"renew\": false,\n                    \"advert_id\": 34326,\n                    \"platforms\": [\n                        {\n                            \"platform\": \"carmine\",\n                            \"designation\": \"Carmine\",\n                            \"logo\": \"https://...\",\n                            \"advert_id\": \"1601032\",\n                            \"status\": \"Ativo\",\n                            \"url\": null\n                        }\n                    ]\n                }\n            ]\n        }\n    }","operationId":"get_listing_integrazu_exports_api_listings__listing_id__integrazu_exports_get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Listing Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Listing Integrazu Exports Api Listings  Listing Id  Integrazu Exports Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/similar-by-vehicle/{viatura_id}":{"get":{"tags":["Listings - Admin"],"summary":"Get Similar Vehicles For Copy","description":"Find similar vehicles (same brand+model) that have existing listings.","operationId":"get_similar_vehicles_for_copy_api_listings_similar_by_vehicle__viatura_id__get","parameters":[{"name":"viatura_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Viatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/listings/copy-from-similar":{"post":{"tags":["Listings - Admin"],"summary":"Copy Listing From Similar","description":"Copy listing from a similar vehicle to create a new listing for a target vehicle.","operationId":"copy_listing_from_similar_api_listings_copy_from_similar_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/articles":{"post":{"tags":["Articles - Admin"],"summary":"Create a new article","operationId":"add_article_api_articles_post","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Article"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/articles/{article_id}":{"put":{"tags":["Articles - Admin"],"summary":"Update an existing article","operationId":"edit_article_api_articles__article_id__put","parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Article Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Article"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Articles - Admin"],"summary":"Delete an article","operationId":"remove_article_api_articles__article_id__delete","parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Article Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/banners/{banner_id}":{"get":{"tags":["Banners - Admin"],"summary":"Get a Specific Banner for Editing","operationId":"get_banner_api_banners__banner_id__get","parameters":[{"name":"banner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Banner Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Banner"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Banners - Admin"],"summary":"Update an existing banner","operationId":"edit_banner_api_banners__banner_id__put","parameters":[{"name":"banner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Banner Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Edit Banner Api Banners  Banner Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Banners - Admin"],"summary":"Delete a banner","operationId":"remove_banner_api_banners__banner_id__delete","parameters":[{"name":"banner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Banner Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Remove Banner Api Banners  Banner Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/banners":{"post":{"tags":["Banners - Admin"],"summary":"Create a new banner","operationId":"add_banner_api_banners_post","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add Banner Api Banners Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reviews":{"post":{"tags":["Reviews - Admin"],"summary":"Create a new review","operationId":"add_review_api_reviews_post","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add Review Api Reviews Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reviews/{review_id}":{"put":{"tags":["Reviews - Admin"],"summary":"Update an existing review","operationId":"edit_review_api_reviews__review_id__put","parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Review Id"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Edit Review Api Reviews  Review Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Reviews - Admin"],"summary":"Delete a review","operationId":"remove_review_api_reviews__review_id__delete","parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Review Id"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams":{"post":{"tags":["Teams - Admin"],"summary":"Create a new team member","operationId":"add_member_api_teams_post","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add Member Api Teams Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams/{member_id}":{"put":{"tags":["Teams - Admin"],"summary":"Update a team member","operationId":"edit_member_api_teams__member_id__put","parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Member Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Edit Member Api Teams  Member Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Teams - Admin"],"summary":"Delete a team member","operationId":"remove_member_api_teams__member_id__delete","parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Member Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams-management":{"get":{"tags":["Teams - Admin"],"summary":"List all CRM teams for user's company","description":"List all teams for the current user's company.","operationId":"get_all_teams_api_teams_management_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get All Teams Api Teams Management Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Teams - Admin"],"summary":"Create a new CRM team","description":"Create a new team for the user's company.","operationId":"create_new_team_api_teams_management_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create New Team Api Teams Management Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams-management/{team_id}":{"get":{"tags":["Teams - Admin"],"summary":"Get a single CRM team by ID","description":"Get a specific team by ID.","operationId":"get_single_team_api_teams_management__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Single Team Api Teams Management  Team Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Teams - Admin"],"summary":"Update a CRM team","description":"Update an existing team.","operationId":"update_existing_team_api_teams_management__team_id__put","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Existing Team Api Teams Management  Team Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Teams - Admin"],"summary":"Team deletion is disabled","description":"Team deletion is disabled for tenant users.\n\nDeleting a team orphans UserTeams/Team_Leaders rows and leaves\nZ_Leads.teams_id attribution stale, so no company user (not even an\nadmin) may delete an Equipa. system_admin escape hatches stay in\napp/routes/admin.py.","operationId":"delete_existing_team_api_teams_management__team_id__delete","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams-management/{team_id}/members":{"get":{"tags":["Teams - Admin"],"summary":"List all members of a CRM team","description":"List all users in a specific team.","operationId":"get_members_of_team_api_teams_management__team_id__members_get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Members Of Team Api Teams Management  Team Id  Members Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user-teams":{"get":{"tags":["Teams - Admin"],"summary":"List user-team associations","description":"List user-team associations with optional filters.","operationId":"get_user_team_list_api_user_teams_get","parameters":[{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Team Id"}},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"User Id"}},{"name":"include_leadership","in":"query","required":false,"schema":{"type":"boolean","description":"When true, also include teams where the user is a leader but not a commercial member. Used by the lead-assignment dropdown.","default":false,"title":"Include Leadership"},"description":"When true, also include teams where the user is a leader but not a commercial member. Used by the lead-assignment dropdown."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get User Team List Api User Teams Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Teams - Admin"],"summary":"Add a user to a team","description":"Add a user to a team.","operationId":"add_user_to_team_api_user_teams_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add User To Team Api User Teams Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user-teams/{user_team_id}":{"get":{"tags":["Teams - Admin"],"summary":"Get a single user-team association","description":"Get a specific user-team association by ID.","operationId":"get_user_team_by_id_endpoint_api_user_teams__user_team_id__get","parameters":[{"name":"user_team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get User Team By Id Endpoint Api User Teams  User Team Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Teams - Admin"],"summary":"Update a user-team association","description":"Update a user-team association.","operationId":"update_user_team_endpoint_api_user_teams__user_team_id__put","parameters":[{"name":"user_team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update User Team Endpoint Api User Teams  User Team Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Teams - Admin"],"summary":"Remove a user from a team","description":"Remove a user from a team.","operationId":"delete_user_team_endpoint_api_user_teams__user_team_id__delete","parameters":[{"name":"user_team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams-management/{team_id}/leaders":{"get":{"tags":["Teams - Admin"],"summary":"List all leaders of a team","description":"List all leaders for a specific team.","operationId":"get_team_leaders_endpoint_api_teams_management__team_id__leaders_get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Team Leaders Endpoint Api Teams Management  Team Id  Leaders Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Teams - Admin"],"summary":"Add a leader to a team","description":"Add a user as a team leader.","operationId":"add_team_leader_endpoint_api_teams_management__team_id__leaders_post","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add Team Leader Endpoint Api Teams Management  Team Id  Leaders Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams-management/{team_id}/leaders/{user_id}":{"delete":{"tags":["Teams - Admin"],"summary":"Remove a leader from a team","description":"Remove a user from team leaders.","operationId":"remove_team_leader_endpoint_api_teams_management__team_id__leaders__user_id__delete","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Team Id"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/achievements":{"post":{"tags":["Achievements - Admin"],"summary":"Create a new achievement","description":"Admin: create new achievement for a website.","operationId":"add_achievement_api_achievements_post","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add Achievement Api Achievements Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/achievements/{achv_id}":{"put":{"tags":["Achievements - Admin"],"summary":"Update an achievement","description":"Admin: update an existing achievement.","operationId":"edit_achievement_api_achievements__achv_id__put","parameters":[{"name":"achv_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Achv Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Edit Achievement Api Achievements  Achv Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Achievements - Admin"],"summary":"Delete an achievement","description":"Admin: delete an achievement.","operationId":"remove_achievement_api_achievements__achv_id__delete","parameters":[{"name":"achv_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Achv Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/partners":{"post":{"tags":["Partners - Admin"],"summary":"Create a new partner","description":"Admin: create a new partner.","operationId":"add_partner_api_partners_post","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add Partner Api Partners Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/partners/{partner_id}":{"put":{"tags":["Partners - Admin"],"summary":"Update an existing partner","description":"Admin: update partner details.","operationId":"edit_partner_api_partners__partner_id__put","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Edit Partner Api Partners  Partner Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Partners - Admin"],"summary":"Delete a partner","description":"Admin: delete a partner.","operationId":"remove_partner_api_partners__partner_id__delete","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contacts":{"post":{"tags":["Contacts - Admin"],"summary":"Submit a new contact form message","description":"Public endpoint for submitting contact or inquiry forms.\nExpected fields:\n- `nome`\n- `email`\n- `telefone`\n- `message`\n- `idpv` (ponto de venda)","operationId":"post_contact_api_contacts_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Contact form payload","title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Post Contact Api Contacts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sitemap/generate":{"post":{"tags":["Sitemap - Admin"],"summary":"Generate and upload a sitemap for a website","description":"Generates and uploads the sitemap for a given website ID.\nOnly available to authenticated users.","operationId":"generate_sitemap_api_sitemap_generate_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SitemapRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/services":{"post":{"tags":["Services - Admin"],"summary":"Create a new website service link","operationId":"add_website_service_link_api_services_post","parameters":[{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add Website Service Link Api Services Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/services/{link_id}":{"get":{"tags":["Services - Admin"],"summary":"Get a specific website service link","operationId":"get_website_service_link_api_services__link_id__get","parameters":[{"name":"link_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Link Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Website Service Link Api Services  Link Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Services - Admin"],"summary":"Update a website service link","operationId":"edit_website_service_link_api_services__link_id__put","parameters":[{"name":"link_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Link Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Edit Website Service Link Api Services  Link Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Services - Admin"],"summary":"Delete a website service link","operationId":"remove_website_service_link_api_services__link_id__delete","parameters":[{"name":"link_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Link Id"}},{"name":"x-website-token","in":"header","required":true,"schema":{"type":"string","title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Remove Website Service Link Api Services  Link Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads":{"post":{"tags":["Leads - Admin"],"summary":"Create a lead from the backoffice","description":"Create a lead by hand from the backoffice (\"Criar Lead\" dialog).\n\nWhy this exists instead of reusing POST /public/leads, which the dialog used\nto call:\n\n* **Identity.** The public route depends on `get_current_user_optional`,\n  which does NOT apply the `x-admin-company` / Z_UserCompanyAccess override\n  (that lives in `get_current_user`). So while impersonating, the vehicle\n  picker listed company X's cars and the lead was filed under the\n  operator's HOME company. On the protected router the two agree.\n* **`object_id` id space.** The picker sends a `Viatura.ID`; a website form\n  sends a `ViaturasEasyDataGreen.ID`. The ranges overlap, so the historical\n  \"convert every object_id through the listing table\" step silently\n  re-pointed a hand-picked car at an unrelated one (measured: 656 of\n  company 1's vehicles would land on a different car of the same company,\n  204 on another tenant's). Here the field is named `vehicle_id` and the id\n  space is declared, not guessed.\n* **Mass assignment.** The public route merges unknown raw-form keys into\n  the payload before it knows who the caller is. This route takes declared\n  params only.\n\nPOST /public/leads keeps working unchanged for website forms AND for cached\nfrontend bundles still posting there.","operationId":"create_lead_backoffice_api_leads_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_create_lead_backoffice_api_leads_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Leads - Admin"],"summary":"List leads with filters","operationId":"api_list_leads_api_leads_get","parameters":[{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by attribution funnel (legacy single; matches Z_Leads.teams_id)","title":"Team Id"},"description":"Filter by attribution funnel (legacy single; matches Z_Leads.teams_id)"},{"name":"team_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Filter by one or more attribution funnels ('Fluxo de Atribuição') — matches leads attributed to any selected funnel (Z_Leads.teams_id), regardless of who owns them now. NOT owner membership.","title":"Team Ids"},"description":"Filter by one or more attribution funnels ('Fluxo de Atribuição') — matches leads attributed to any selected funnel (Z_Leads.teams_id), regardless of who owns them now. NOT owner membership."},{"name":"stage","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"}},{"name":"lead_stage","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lead Stage"}},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by user (legacy single)","title":"User Id"},"description":"Filter by user (legacy single)"},{"name":"user_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Filter by one or more users — matches leads owned by any of them","title":"User Ids"},"description":"Filter by one or more users — matches leads owned by any of them"},{"name":"scope","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"'mine' = role-aware board view: the caller's own leads, plus all team leads if the caller is a team leader","title":"Scope"},"description":"'mine' = role-aware board view: the caller's own leads, plus all team leads if the caller is a team leader"},{"name":"lost_reasons","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter lost leads by one or more lost_reason IDs","title":"Lost Reasons"},"description":"Filter lost leads by one or more lost_reason IDs"},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort order: 'created_desc' (newest first) or 'created_asc' (oldest first)","default":"created_desc","title":"Sort"},"description":"Sort order: 'created_desc' (newest first) or 'created_asc' (oldest first)"},{"name":"date_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only leads created on/after this date (YYYY-MM-DD)","title":"Date Start"},"description":"Only leads created on/after this date (YYYY-MM-DD)"},{"name":"date_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only leads created on/before this date, inclusive (YYYY-MM-DD)","title":"Date End"},"description":"Only leads created on/before this date, inclusive (YYYY-MM-DD)"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1000,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/teams":{"get":{"tags":["Leads - Admin"],"summary":"List Teams for the Company","description":"Returns all Teams for the authenticated user's company.","operationId":"api_get_teams_api_leads_teams_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/origins":{"get":{"tags":["Leads - Admin"],"summary":"Declared-origin taxonomy for the Adicionar Lead selector","description":"Options for the manual \"Origem da lead\" selector (ticket #726).\n\nServed from the backend so the frontend cannot drift from the keys actually\npersisted in Z_Leads.declared_origin — the mistake SOURCE_OPTIONS /\nREQUEST_SOURCE_LABELS already made in call-tracking, where two hand-synced\ncopies of the same list live in two repos.\n\nThe list is GLOBAL, not tenant-scoped: a declared \"standvirtual\" has to be\nthe same key for every company or it stops being comparable to the measured\none. Hence no idcompany here — there is no tenant data to leak. Auth still\napplies (protected_router is gated globally).","operationId":"api_list_lead_origins_api_leads_origins_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/owners":{"get":{"tags":["Leads - Admin"],"summary":"List distinct lead-owning users for the company","description":"Source list for the leads board's Utilizador filter.\n\nRestricts to users who own at least one lead in Z_Leads for the current\ncompany. Pulled from Z_Leads (not UserTeams) so a former team member with\nhistorical leads remains selectable in the filter.","operationId":"api_list_lead_owners_api_leads_owners_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/reports/attribution-reliability":{"get":{"tags":["Leads - Admin"],"summary":"Measured vs declared attribution on won leads","description":"The statistic ticket #726 actually asked for.\n\nNot \"where did leads come from\" — that is the sources report. This answers\n\"how much of that answer can I trust\", by splitting won leads into origins a\nsalesperson TYPED versus origins the system MEASURED, plus the pre-feature\nrows nobody was ever asked about.\n\nRegistered above /leads/reports/{...}-style paths and well before\n/leads/{lead_id} (defined much later in this module), so the literal path\nwins the match.","operationId":"api_attribution_reliability_api_leads_reports_attribution_reliability_get","parameters":[{"name":"team_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Team Id"}},{"name":"include_no_funnel","in":"query","required":false,"schema":{"type":"boolean","description":"Also match leads with no (or an orphaned) attribution funnel","default":false,"title":"Include No Funnel"},"description":"Also match leads with no (or an orphaned) attribution funnel"},{"name":"period","in":"query","required":false,"schema":{"type":"string","default":"30","title":"Period"}},{"name":"month","in":"query","required":false,"schema":{"type":"string","title":"Month"}},{"name":"start_date","in":"query","required":false,"schema":{"type":"string","title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"type":"string","title":"End Date"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/reports":{"get":{"tags":["Leads - Admin"],"summary":"CRM Reports","operationId":"api_crm_reports_api_leads_reports_get","parameters":[{"name":"team_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Team Id"}},{"name":"include_no_funnel","in":"query","required":false,"schema":{"type":"boolean","description":"Also match leads with no (or an orphaned) attribution funnel","default":false,"title":"Include No Funnel"},"description":"Also match leads with no (or an orphaned) attribution funnel"},{"name":"period","in":"query","required":false,"schema":{"type":"string","default":"30","title":"Period"}},{"name":"month","in":"query","required":false,"schema":{"type":"string","title":"Month"}},{"name":"start_date","in":"query","required":false,"schema":{"type":"string","title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"type":"string","title":"End Date"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/reports/lost-reason-leads":{"get":{"tags":["Leads - Admin"],"summary":"Leads behind one 'Motivos de Perda' row (paged drill-down)","description":"Page through the leads of one card row, newest loss first.\n\n`start_date`/`end_date` are REQUIRED and are the `window` the report echoed:\nthe dialog must show the same population the card counted, and re-deriving\nthe window from `period` at click time would drift by the page's dwell time.\n\nA card row can cover several stored values (the FE merges by resolved label),\nhence `reason` is repeatable; `include_no_reason` selects the NULL/blank\n\"Sem motivo indicado\" bucket, which `IN (...)` can never match.","operationId":"api_lost_reason_leads_api_leads_reports_lost_reason_leads_get","parameters":[{"name":"reason","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"default":[],"title":"Reason"}},{"name":"include_no_reason","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include No Reason"}},{"name":"start_date","in":"query","required":false,"schema":{"type":"string","title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"type":"string","title":"End Date"}},{"name":"team_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Team Id"}},{"name":"include_no_funnel","in":"query","required":false,"schema":{"type":"boolean","description":"Also match leads with no (or an orphaned) attribution funnel","default":false,"title":"Include No Funnel"},"description":"Also match leads with no (or an orphaned) attribution funnel"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":100,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/sources-quality":{"get":{"tags":["Leads - Admin"],"summary":"Active Leads Quality by Source","description":"Returns active leads grouped by source, campaign and stage.\nNo date filtering - shows current snapshot of all active leads.","operationId":"api_leads_sources_quality_api_leads_sources_quality_get","parameters":[{"name":"team_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Team Id"}},{"name":"include_no_funnel","in":"query","required":false,"schema":{"type":"boolean","description":"Also match leads with no (or an orphaned) attribution funnel","default":false,"title":"Include No Funnel"},"description":"Also match leads with no (or an orphaned) attribution funnel"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/reports/user/{user_id}":{"get":{"tags":["Leads - Admin"],"summary":"User Detailed Report","description":"Per-commercial drill-down, opened from a row of the report's\n\"Performance por Comercial\" table.\n\nTakes the SAME funnel filter as the parent report, and the caller should\nsend the report's echoed `window` as start_date/end_date rather than\n`period`: the row was computed for one funnel and one resolved window, so\nre-deriving either here would make the modal contradict the row that opened\nit (the same pinning the lost-reason drill-down does).","operationId":"api_user_report_api_leads_reports_user__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"team_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Team Id"}},{"name":"include_no_funnel","in":"query","required":false,"schema":{"type":"boolean","description":"Also match leads with no (or an orphaned) attribution funnel","default":false,"title":"Include No Funnel"},"description":"Also match leads with no (or an orphaned) attribution funnel"},{"name":"period","in":"query","required":false,"schema":{"type":"string","default":"30","title":"Period"}},{"name":"month","in":"query","required":false,"schema":{"type":"string","title":"Month"}},{"name":"start_date","in":"query","required":false,"schema":{"type":"string","title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"type":"string","title":"End Date"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/by-viatura/{id_viatura}":{"get":{"tags":["Leads - Admin"],"summary":"Get won lead for a vehicle","description":"Find the won lead associated with a vehicle.\n\nPass `contract_id` when the caller is looking at one specific contract: the\nrecorded Contratos.lead_id then answers instead of the by-vehicle guess,\nwhich cannot tell two sales of the same car apart.","operationId":"api_get_won_lead_by_vehicle_api_leads_by_viatura__id_viatura__get","parameters":[{"name":"id_viatura","in":"path","required":true,"schema":{"type":"integer","title":"Id Viatura"}},{"name":"contract_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Prefer the lead explicitly linked to this contract","title":"Contract Id"},"description":"Prefer the lead explicitly linked to this contract"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/search":{"get":{"tags":["Leads - Admin"],"summary":"Search leads across the company","operationId":"api_search_leads_api_leads_search_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"stage","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"}},{"name":"lead_stage","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lead Stage"}},{"name":"date_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Start"}},{"name":"date_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date End"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/tasks":{"get":{"tags":["Leads - Admin"],"summary":"List all tasks for current user or company","operationId":"api_list_user_tasks_route_api_leads_tasks_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Limit"}},{"name":"include_completed","in":"query","required":false,"schema":{"type":"boolean","description":"Include completed tasks","default":false,"title":"Include Completed"},"description":"Include completed tasks"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Api List User Tasks Route Api Leads Tasks Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/history":{"get":{"tags":["Leads - Admin"],"summary":"List all lead history","operationId":"api_list_user_history_route_api_leads_history_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/queue":{"get":{"tags":["Leads - Admin"],"summary":"List queued leads for company","description":"List leads currently in queue (waiting for assignment).","operationId":"api_list_queued_leads_api_leads_queue_get","parameters":[{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by team","title":"Team Id"},"description":"Filter by team"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/queue/{team_id}":{"get":{"tags":["Leads - Admin"],"summary":"List queued leads for a team","description":"List queued leads for a specific team.","operationId":"api_list_team_queued_leads_api_leads_queue__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/queue/{queue_id}/assign":{"post":{"tags":["Leads - Admin"],"summary":"Manually assign a queued lead","description":"Manually assign a queued lead to a user.\nBody: { \"assigned_user_id\": 123 } or {} for round-robin.","operationId":"api_assign_queued_lead_api_leads_queue__queue_id__assign_post","parameters":[{"name":"queue_id","in":"path","required":true,"schema":{"type":"integer","title":"Queue Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}":{"get":{"tags":["Leads - Admin"],"summary":"Api Get Lead","operationId":"api_get_lead_api_leads__lead_id__get","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Get Lead Api Leads  Lead Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Leads - Admin"],"summary":"Api Update Lead","operationId":"api_update_lead_api_leads__lead_id__put","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/tasks":{"get":{"tags":["Leads - Admin"],"summary":"Api List Tasks","operationId":"api_list_tasks_api_leads__lead_id__tasks_get","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TaskDTO"},"title":"Response Api List Tasks Api Leads  Lead Id  Tasks Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Leads - Admin"],"summary":"Api Create Task","operationId":"api_create_task_api_leads__lead_id__tasks_post","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"integer","title":"Response Api Create Task Api Leads  Lead Id  Tasks Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/tasks/{task_id}/complete":{"put":{"tags":["Leads - Admin"],"summary":"Api Complete Task","operationId":"api_complete_task_api_leads__lead_id__tasks__task_id__complete_put","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"task_id","in":"path","required":true,"schema":{"type":"integer","title":"Task Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/tasks/{task_id}":{"put":{"tags":["Leads - Admin"],"summary":"Api Update Task","operationId":"api_update_task_api_leads__lead_id__tasks__task_id__put","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"task_id","in":"path","required":true,"schema":{"type":"integer","title":"Task Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Leads - Admin"],"summary":"Api Delete Task","operationId":"api_delete_task_api_leads__lead_id__tasks__task_id__delete","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"task_id","in":"path","required":true,"schema":{"type":"integer","title":"Task Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/accept":{"put":{"tags":["Leads - Admin"],"summary":"Api Accept Lead","description":"Accept a lead and optionally assign to a team with round-robin attribution.\n\nRequest body options:\n- {} - Just accept the lead (no attribution)\n- { \"team_id\": 456 } - Accept, update team, and run round-robin attribution with notifications","operationId":"api_accept_lead_api_leads__lead_id__accept_put","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/assign":{"post":{"tags":["Leads - Admin"],"summary":"Api Assign Lead","description":"Assign/reassign a lead to a user or team.\nSends SMS and email notifications like POST /public/leads.\n\nRequest body options:\n- { \"assigned_user_id\": 123 } - Direct assignment to specific user\n- { \"team_id\": 456 } - Round-robin assignment within team\n\nReturns the assigned user info.","operationId":"api_assign_lead_api_leads__lead_id__assign_post","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/vehicle":{"delete":{"tags":["Leads - Admin"],"summary":"Api Remove Vehicle","operationId":"api_remove_vehicle_api_leads__lead_id__vehicle_delete","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Leads - Admin"],"summary":"Api Assign Vehicle","operationId":"api_assign_vehicle_api_leads__lead_id__vehicle_put","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/appraisals":{"post":{"tags":["Leads - Admin"],"summary":"Api Attach Appraisal","operationId":"api_attach_appraisal_api_leads__lead_id__appraisals_post","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/appraisals/{appraisal_id}":{"delete":{"tags":["Leads - Admin"],"summary":"Api Detach Appraisal","operationId":"api_detach_appraisal_api_leads__lead_id__appraisals__appraisal_id__delete","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"appraisal_id","in":"path","required":true,"schema":{"type":"integer","title":"Appraisal Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/history":{"get":{"tags":["Leads - Admin"],"summary":"Api List History","operationId":"api_list_history_api_leads__lead_id__history_get","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/HistoryDTO"},"title":"Response Api List History Api Leads  Lead Id  History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Leads - Admin"],"summary":"Api Create History","operationId":"api_create_history_api_leads__lead_id__history_post","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"integer","title":"Response Api Create History Api Leads  Lead Id  History Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads/{lead_id}/redistributions":{"get":{"tags":["Leads - Admin"],"summary":"Get redistribution history","description":"View redistribution history for a lead.","operationId":"api_get_redistributions_api_leads__lead_id__redistributions_get","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/meta/connect/{team_id}":{"get":{"tags":["Meta OAuth"],"summary":"Meta Connect","description":"Start Meta OAuth flow. Redirects user to Facebook login.\nAfter authorization, Facebook redirects to /api/meta/callback.","operationId":"meta_connect_api_meta_connect__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/meta/callback":{"get":{"tags":["Meta OAuth"],"summary":"Meta Callback","description":"Facebook OAuth callback. Exchanges code for permanent page tokens.","operationId":"meta_callback_api_meta_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"type":"string","title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","title":"State"}},{"name":"error","in":"query","required":false,"schema":{"type":"string","title":"Error"}},{"name":"error_description","in":"query","required":false,"schema":{"type":"string","title":"Error Description"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/client-prospects":{"post":{"tags":["Client Prospect - Admin"],"summary":"Create a new client prospect","description":"Create a new client prospect.\nidcompany is automatically extracted from the authenticated user.","operationId":"create_client_prospect_api_client_prospects_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/client-prospects/{prospect_id}":{"put":{"tags":["Client Prospect - Admin"],"summary":"Update an existing client prospect","description":"Updates editable fields (name, email, phone, etc.) of a client prospect by ID.\nidcompany is verified from the authenticated user for security.","operationId":"edit_client_prospect_api_client_prospects__prospect_id__put","parameters":[{"name":"prospect_id","in":"path","required":true,"schema":{"type":"integer","title":"Prospect Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/client-prospects/{prospect_id}/resolve-client":{"post":{"tags":["Client Prospect - Admin"],"summary":"Match the prospect to an existing client or create one from it","description":"Lead → contract flow: finds an existing Cliente for this prospect\n(NIF, then email/phone with a name sanity-check) or creates a new one\nfrom the prospect's data. No body — everything comes from the prospect\nrow, tenant-scoped by the authenticated user's idcompany.\n\nReturns {\"status\": \"matched\"|\"created\", \"id_cliente\", \"Nome\", \"matched_by\"}.","operationId":"resolve_client_from_prospect_api_client_prospects__prospect_id__resolve_client_post","parameters":[{"name":"prospect_id","in":"path","required":true,"schema":{"type":"integer","title":"Prospect Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/documents-test/":{"get":{"tags":["documents-test"],"summary":"List documents for a module/record","description":"List documents for a specific module/record with status.\n\nTranslates VBA: PTQ_ListaDocsMerged","operationId":"list_documents_api_documents_test__get","parameters":[{"name":"id_modulo","in":"query","required":true,"schema":{"type":"integer","description":"Module ID (4=Movimentos, 7=PV, 8=Faturas, 12=Cliente)","title":"Id Modulo"},"description":"Module ID (4=Movimentos, 7=PV, 8=Faturas, 12=Cliente)"},{"name":"id_modulo_id","in":"query","required":true,"schema":{"type":"integer","description":"Record ID within the module","title":"Id Modulo Id"},"description":"Record ID within the module"},{"name":"tipodoc","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by document type","title":"Tipodoc"},"description":"Filter by document type"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search in document name","title":"Search"},"description":"Search in document name"},{"name":"include_suggestions","in":"query","required":false,"schema":{"type":"boolean","description":"Include 'em falta' suggested documents","default":true,"title":"Include Suggestions"},"description":"Include 'em falta' suggested documents"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["documents-test"],"summary":"Upload document","description":"Upload a new document.\n\nTranslates VBA: UploadFile","operationId":"create_document_api_documents_test__post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_document_api_documents_test__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Document Api Documents Test  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/documents-test/{document_id}":{"get":{"tags":["documents-test"],"summary":"Get single document","description":"Get a single document by ID with presigned URL.","operationId":"get_document_api_documents_test__document_id__get","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"integer","title":"Document Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Document Api Documents Test  Document Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["documents-test"],"summary":"Update document metadata","description":"Update document metadata (name, type, expiration, etc).","operationId":"update_document_api_documents_test__document_id__put","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"integer","title":"Document Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Document Api Documents Test  Document Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["documents-test"],"summary":"Delete document","description":"Delete a document and its S3 file.\n\nTranslates VBA: DeleteFile","operationId":"delete_document_api_documents_test__document_id__delete","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"integer","title":"Document Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Document Api Documents Test  Document Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/documents-test/types/list":{"get":{"tags":["documents-test"],"summary":"Get document types","description":"Get document types for dropdowns (global types + the caller's own custom types).","operationId":"get_document_types_api_documents_test_types_list_get","parameters":[{"name":"id_modulo","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by module ID","title":"Id Modulo"},"description":"Filter by module ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentTypesListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/documents-test/types":{"post":{"tags":["documents-test"],"summary":"Create a company-specific document type","description":"Create a tenant-specific document type (TipoDocsNomeModulo) so users can add\none inline from the Documentos tab when no existing type matches. Scoped to\nthe caller's company (invisible to other tenants). Dedupes on name+module\n(returns the existing global/own type instead of a duplicate).\n\nBody: { name: str, id_modulo: int }","operationId":"create_document_type_api_documents_test_types_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/documents-test/{document_id}/send-supplier":{"post":{"tags":["documents-test"],"summary":"Send document to supplier","description":"Send document to supplier/client via email.\n\nTranslates VBA: sendprooftosupplier\nNote: Only works for payment proofs (Tipodoc=59)","operationId":"send_to_supplier_api_documents_test__document_id__send_supplier_post","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"integer","title":"Document Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__models__documents__SendEmailResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/documents-test/{document_id}/send-accountant":{"post":{"tags":["documents-test"],"summary":"Send document to accountant","description":"Send document to accountant via email.\n\nTranslates VBA: SendtoToc","operationId":"send_to_accountant_api_documents_test__document_id__send_accountant_post","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"integer","title":"Document Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__models__documents__SendEmailResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/documents-test/{document_id}/archive-status":{"get":{"tags":["documents-test"],"summary":"TOConline archive status of the document's latest accountant send","description":"Latest Z_TocArchiveSends row for this document (source='documento') —\nthe DocumentViewDialog status chip. Empty dict when the document was\nnever sent (or sent before the feedback loop shipped).\nPlain `def` on purpose: sync pyodbc (see 10-api-patterns.md).","operationId":"get_document_archive_status_api_documents_test__document_id__archive_status_get","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"integer","title":"Document Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/documents-test/lote/{file_group_id}/send-supplier":{"post":{"tags":["documents-test"],"summary":"Enviar comprovativo de pagamento em lote ao fornecedor","description":"Send a grouped payment proof (batch comprovativo) to the supplier —\nONE email per group, listing every covered document.","operationId":"send_group_to_supplier_api_documents_test_lote__file_group_id__send_supplier_post","parameters":[{"name":"file_group_id","in":"path","required":true,"schema":{"type":"string","title":"File Group Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__models__documents__SendEmailResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/documents-test/lote/{file_group_id}/send-accountant":{"post":{"tags":["documents-test"],"summary":"Enviar comprovativo de pagamento em lote à contabilidade","description":"Send a grouped payment proof (batch comprovativo) to the PV's\naccountant(s) — ONE email per configured address, once per group.","operationId":"send_group_to_accountant_api_documents_test_lote__file_group_id__send_accountant_post","parameters":[{"name":"file_group_id","in":"path","required":true,"schema":{"type":"string","title":"File Group Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__models__documents__SendEmailResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bank_rows":{"get":{"tags":["Bank - Admin"],"summary":"Api List Bank Rows","description":"List filtered bank rows. Active movements by default; only_ignored=True returns only ignored ones.","operationId":"api_list_bank_rows_api_bank_rows_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"todos","title":"Status"}},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start"}},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End"}},{"name":"metodo_pagamento_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Metodo Pagamento Id"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ponto Venda Id"}},{"name":"only_ignored","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Only Ignored"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BankRow"},"title":"Response Api List Bank Rows Api Bank Rows Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bank_rows/import":{"post":{"tags":["Bank - Admin"],"summary":"Api Import Bank Rows","description":"Import bank movements from an N43 (AEB/CSB 43) statement file.\n\nMovements dated inside a period this account already holds are skipped, so the\ndealer's daily rolling export stops duplicating history it has already reconciled.","operationId":"api_import_bank_rows_api_bank_rows_import_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_api_import_bank_rows_api_bank_rows_import_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bank_statements":{"get":{"tags":["Bank - Admin"],"summary":"Api List Bank Statements","description":"Statements imported for an account, newest first.\n\n`limit` is honoured because the statement list is the ONLY route to deleting a\nwrongly-imported extrato: with the old fixed TOP 12, a mistake made a few weeks of\ndaily imports ago silently fell off the list and became unreachable.","operationId":"api_list_bank_statements_api_bank_statements_get","parameters":[{"name":"metodo_pagamento_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Metodo Pagamento Id"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ponto Venda Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":12,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bank_statements/{statement_id}":{"get":{"tags":["Bank - Admin"],"summary":"Api Get Bank Statement","description":"One statement with its movements in file order and a running balance.\n\nThe balance is only meaningful here: the main reconciliation grid is filtered by\nstatus/date/ignored and sorted by date, and a running total over a filtered,\nre-sorted subset would be a lie. It is computed on read, never stored.\n\n`links` + `can_force_delete` let the UI show what a deletion would destroy (which\ninvoices go back to \"não conciliada\") and whether this caller may confirm it, so the\ndelete dialog never has to guess at the server's permission rules.","operationId":"api_get_bank_statement_api_bank_statements__statement_id__get","parameters":[{"name":"statement_id","in":"path","required":true,"schema":{"type":"integer","title":"Statement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Bank - Admin"],"summary":"Api Delete Bank Statement","description":"Delete a statement and its movements (child-first).\n\nThis is what makes the file-hash idempotency safe: without a way to remove a\nstatement, a file imported by mistake — or under the wrong account — could never be\nre-imported.\n\nThe gate is conditional rather than a blanket `admin` dependency. A statement with\nno invoice links is fully recoverable by re-importing the file, so anyone who may\nimport may also delete one — the previous admin-only rule left ordinary users stuck\nwith their own mistake. A statement WITH links is bulk-destructive (deleting it\nfrees invoices that were matched), so it needs a company admin who passed `force`\nafter being shown the affected invoices.","operationId":"api_delete_bank_statement_api_bank_statements__statement_id__delete","parameters":[{"name":"statement_id","in":"path","required":true,"schema":{"type":"integer","title":"Statement Id"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bank_rows/{bank_id}/toggle-reconciled":{"post":{"tags":["Bank - Admin"],"summary":"Api Toggle Reconciled","description":"Toggle the reconciled flag on a bank movement.","operationId":"api_toggle_reconciled_api_bank_rows__bank_id__toggle_reconciled_post","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bank_rows/{bank_id}/ignore":{"post":{"tags":["Bank - Admin"],"summary":"Api Ignore Movement","description":"Ignore (hide) a bank movement with a required justification.","operationId":"api_ignore_movement_api_bank_rows__bank_id__ignore_post","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IgnorePayload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bank_rows/{bank_id}/unignore":{"post":{"tags":["Bank - Admin"],"summary":"Api Unignore Movement","description":"Reverse an ignore on a bank movement.","operationId":"api_unignore_movement_api_bank_rows__bank_id__unignore_post","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bank_rows/ignore-bulk":{"post":{"tags":["Bank - Admin"],"summary":"Api Ignore Movements Bulk","description":"Ignore (hide) several bank movements at once, with one shared justification.","operationId":"api_ignore_movements_bulk_api_bank_rows_ignore_bulk_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IgnoreBulkPayload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bank_rows/delete":{"post":{"tags":["Bank - Admin"],"summary":"Api Delete Bank Rows","description":"Delete bank rows by ID list.","operationId":"api_delete_bank_rows_api_bank_rows_delete_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletePayload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reconcile/{bank_id}/propose":{"post":{"tags":["Reconcile - Admin"],"summary":"Api Propose Reconciliation","description":"Return reconciliation proposals for a given bank movement.","operationId":"api_propose_reconciliation_api_reconcile__bank_id__propose_post","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Api Propose Reconciliation Api Reconcile  Bank Id  Propose Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reconcile/{bank_id}/details":{"get":{"tags":["Reconcile - Admin"],"summary":"Api Reconciliation Details","description":"Return reconciled invoice details for a specific bank movement.","operationId":"api_reconciliation_details_api_reconcile__bank_id__details_get","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Api Reconciliation Details Api Reconcile  Bank Id  Details Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reconcile/{bank_id}/accept":{"post":{"tags":["Reconcile - Admin"],"summary":"Api Accept Reconciliation","description":"Accept selected invoices for reconciliation.","operationId":"api_accept_reconciliation_api_reconcile__bank_id__accept_post","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reconcile/bulk-propose":{"post":{"tags":["Reconcile - Admin"],"summary":"Api Bulk Propose Reconciliation","description":"Return proposals matching the combined total of multiple bank movements.","operationId":"api_bulk_propose_reconciliation_api_reconcile_bulk_propose_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reconcile/bulk-accept":{"post":{"tags":["Reconcile - Admin"],"summary":"Api Bulk Accept Reconciliation","description":"Accept selected invoices for multiple bank movements at once.","operationId":"api_bulk_accept_reconciliation_api_reconcile_bulk_accept_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reconcile/{bank_id}/move":{"post":{"tags":["Reconcile - Admin"],"summary":"Api Move Reconciliation","description":"Move an already-accepted invoice from another bank movement onto this one.\n\nPowers the \"Mover para este movimento\" action on a greyed-out search result —\nthe recovery path for an invoice that was reconciled against the wrong\nmovement (same amount, different car) and is therefore unusable everywhere else.","operationId":"api_move_reconciliation_api_reconcile__bank_id__move_post","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reconcile/{bank_id}/complement":{"post":{"tags":["Reconcile - Admin"],"summary":"Api Complement Reconciliation","description":"Link an invoice already (partially) consumed by other movements to this one\ntoo, covering the rest of its value — the \"Complementar\" button.\n\nThe client sends only {fatura_id}; the amount is computed server-side as\nmin(invoice remaining, movement remaining) from live data inside the\ntransaction, so a stale search snapshot can never over-allocate.","operationId":"api_complement_reconciliation_api_reconcile__bank_id__complement_post","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reconcile/{bank_id}/unaccept":{"post":{"tags":["Reconcile - Admin"],"summary":"Api Unaccept Reconciliation","description":"Remove all accepted reconciliations for a bank movement.","operationId":"api_unaccept_reconciliation_api_reconcile__bank_id__unaccept_post","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reconcile/{bank_id}/unaccept_partial":{"post":{"tags":["Reconcile - Admin"],"summary":"Api Unaccept Partial Reconciliation","description":"Remove only selected reconciled invoices for a bank movement.","operationId":"api_unaccept_partial_reconciliation_api_reconcile__bank_id__unaccept_partial_post","parameters":[{"name":"bank_id","in":"path","required":true,"schema":{"type":"integer","title":"Bank Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tink/link-url":{"get":{"tags":["Tink - Admin"],"summary":"Api Tink Link Url","description":"Build the hosted Tink Link URL and redirect there.","operationId":"api_tink_link_url_api_tink_link_url_get","parameters":[{"name":"metodoId","in":"query","required":true,"schema":{"type":"integer","description":"ID do Método de Pagamento","title":"Metodoid"},"description":"ID do Método de Pagamento"},{"name":"pv","in":"query","required":true,"schema":{"type":"integer","description":"ID do Ponto de Venda","title":"Pv"},"description":"ID do Ponto de Venda"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tink/credentials/{metodo_id}":{"get":{"tags":["Tink - Admin"],"summary":"Api Get Tink Credentials","description":"Return 200 if tokens exist for metodo_pagamento_id, else 404.","operationId":"api_get_tink_credentials_api_tink_credentials__metodo_id__get","parameters":[{"name":"metodo_id","in":"path","required":true,"schema":{"type":"integer","title":"Metodo Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tink/credentials":{"delete":{"tags":["Tink - Admin"],"summary":"Api Remove Tink Credentials","description":"Delete stored Tink tokens for this payment method.","operationId":"api_remove_tink_credentials_api_tink_credentials_delete","parameters":[{"name":"metodo_pagamento_id","in":"query","required":true,"schema":{"type":"integer","description":"ID do Método de Pagamento","title":"Metodo Pagamento Id"},"description":"ID do Método de Pagamento"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tink/callback":{"get":{"tags":["Tink - Admin"],"summary":"Api Tink Callback","description":"OAuth callback: exchange code for tokens and save them.","operationId":"api_tink_callback_api_tink_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"pv","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pv"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tink/refresh-transactions":{"post":{"tags":["Tink - Admin"],"summary":"Api Refresh Tink Transactions","description":"Fetch transactions from Tink and upsert into bank_movements.","operationId":"api_refresh_tink_transactions_api_tink_refresh_transactions_post","parameters":[{"name":"metodo","in":"query","required":true,"schema":{"type":"integer","description":"ID do Método de Pagamento","title":"Metodo"},"description":"ID do Método de Pagamento"},{"name":"pv","in":"query","required":true,"schema":{"type":"integer","description":"ID do Ponto de Venda","title":"Pv"},"description":"ID do Ponto de Venda"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/metodos_pagamento":{"get":{"tags":["Métodos de Pagamento - Admin"],"summary":"Protected List Metodos Pagamento","description":"Protected endpoint — filters by the user's ponto de venda (from authentication).","operationId":"protected_list_metodos_pagamento_api_metodos_pagamento_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetodoPagamento"},"title":"Response Protected List Metodos Pagamento Api Metodos Pagamento Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Métodos de Pagamento - Admin"],"summary":"Create payment method","description":"Create a new payment method for a PV.\nValidates that the PV belongs to the user's company.\n\nRequired: metodo_pagamento (name), ponto_venda_id\nOptional: obriga_fatura (bool), banco (bool)","operationId":"create_payment_method_api_metodos_pagamento_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/metodos_pagamento/pv/{pv_id}":{"get":{"tags":["Métodos de Pagamento - Admin"],"summary":"List payment methods for a specific PV","description":"List ALL payment methods for a specific PV (tenant-scoped).\nReturns all methods (not just bank ones).","operationId":"list_pv_payment_methods_api_metodos_pagamento_pv__pv_id__get","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/metodos_pagamento/all":{"get":{"tags":["Métodos de Pagamento - Admin"],"summary":"List all payment methods for company","description":"List payment methods across ALL PVs for the user's company.\nUsed during onboarding to check if any payment methods exist.","operationId":"list_all_company_payment_methods_api_metodos_pagamento_all_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/metodos_pagamento/{metodo_id}":{"put":{"tags":["Métodos de Pagamento - Admin"],"summary":"Update payment method","description":"Update a payment method.\nValidates ownership via PV -> company chain.","operationId":"update_payment_method_api_metodos_pagamento__metodo_id__put","parameters":[{"name":"metodo_id","in":"path","required":true,"schema":{"type":"integer","title":"Metodo Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Métodos de Pagamento - Admin"],"summary":"Delete payment method","description":"Deletion of payment methods is not allowed.\nUsers may only add or edit payment methods.","operationId":"delete_payment_method_api_metodos_pagamento__metodo_id__delete","parameters":[{"name":"metodo_id","in":"path","required":true,"schema":{"type":"integer","title":"Metodo Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/brands":{"get":{"tags":["Brands - Admin"],"summary":"List all brands for the company","description":"List all brands (with website info) for the authenticated user's company.","operationId":"list_brands_api_brands_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Brands - Admin"],"summary":"Create a brand","description":"Create a standalone brand for the company.\nRequired: name (brand name).","operationId":"create_brand_endpoint_api_brands_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/brands/{brand_id}":{"put":{"tags":["Brands - Admin"],"summary":"Update a brand","description":"Update a brand name. Validates ownership via idcompany.","operationId":"update_brand_endpoint_api_brands__brand_id__put","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"integer","title":"Brand Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Brands - Admin"],"summary":"Delete a brand","description":"Delete a brand. Only allowed if brand has no linked website.\nValidates ownership via idcompany.","operationId":"delete_brand_endpoint_api_brands__brand_id__delete","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"integer","title":"Brand Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/credits/use":{"post":{"tags":["Credits - Admin"],"summary":"Use Credits Endpoint","description":"Allows a PV to spend credits on a platform action.\n\nReads the PV from `current_user[\"idpointofsale\"]` so admin/PV impersonation\noverrides are honored — credits are deducted from the active context, not\nthe real user's home PV.","operationId":"use_credits_endpoint_api_credits_use_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditUsePayload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/credits/status":{"get":{"tags":["Credits - Admin"],"summary":"Get Credit Status","description":"Get the active PV's current credit balance and billing info.\nIn company billing mode, returns the anchor PV's balance.\n\nReads the PV from `current_user[\"idpointofsale\"]` so admin/PV impersonation\noverrides (x-admin-company / x-active-pv) are honored. Looking up by\nCognito sub would always return the real user's home PV regardless of\nwhich company they're acting as.","operationId":"get_credit_status_api_credits_status_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/credits/logs":{"get":{"tags":["Credits - Admin"],"summary":"List Credit Logs","description":"Protected endpoint: paginated credit logs for the authenticated user's company.\n\nQuery params:\n- page: page number (default 1)\n- limit: records per page (default 50)\n- idpointofsale: filter by one or more PV IDs (omit for all PVs)\n- tipo: \"carregado\" (credits added) or \"utilizado\" (credits used)","operationId":"list_credit_logs_api_credits_logs_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"idpointofsale","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Idpointofsale"}},{"name":"tipo","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tipo"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/credits/company-status":{"get":{"tags":["Credits - Admin"],"summary":"Get Company Status","description":"Get the company's current status (active, negative_balance, or locked).\n\nReturns:\n- status: 'active' | 'negative_balance' | 'locked'\n- days_until_lock: Number of days until lock (only if negative_balance)\n- balance_total_cents: Sum of all PV balances\n- negative_since: Timestamp when company went negative (only if negative_balance or locked)","operationId":"get_company_status_api_credits_company_status_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/payments/start":{"post":{"tags":["Credits - Admin"],"summary":"Start Payment Flow","description":"Initiates a payment transaction with SIBS (MB WAY or Multibanco) to top-up credits.\nIn company billing mode, the payment is stored against the anchor PV so the\nSIBS webhook automatically credits the correct PV.\n\nUses `current_user[\"idpointofsale\"]` so impersonation top-ups go to the\nimpersonated company's PV.","operationId":"start_payment_flow_api_payments_start_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentStartPayload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/payments/local-status":{"get":{"tags":["Payments - Admin"],"summary":"Get Local Payment Status","description":"Fetches the status of a payment transaction from the local DB (no external API calls).","operationId":"get_local_payment_status_api_payments_local_status_get","parameters":[{"name":"transaction_id","in":"query","required":true,"schema":{"type":"string","description":"Merchant transaction ID to check.","title":"Transaction Id"},"description":"Merchant transaction ID to check."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/payments/status":{"get":{"tags":["Payments - Admin"],"summary":"Check Payment Status","description":"Checks the current status of a payment transaction directly from SIBS.","operationId":"check_payment_status_api_payments_status_get","parameters":[{"name":"transaction_id","in":"query","required":true,"schema":{"type":"string","description":"SIBS transaction ID to check.","title":"Transaction Id"},"description":"SIBS transaction ID to check."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/incentives":{"get":{"tags":["Incentives - Admin"],"summary":"Get all active incentive rules","description":"Returns all active credit incentive rules.\nUsed by frontend to display available bonus tiers (e.g., +10% for 50€ top-ups).","operationId":"get_all_incentive_rules_api_incentives_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assets/upload":{"post":{"tags":["Assets - Admin"],"summary":"Upload files to S3","description":"Upload one or more files to the S3 bucket associated with the given website (STAGING).\n\n- Images (PNG, JPG, JPEG, GIF, BMP, TIFF, WEBP) are limited to 1MB and auto-converted to WebP\n- Videos (MP4, WEBM, MOV, AVI) are limited to 30MB (nginx body cap)\n- PDFs are limited to 10MB. Every other type is refused.\n\nReturns `{\"uploaded\": [url, ...], \"failed\": [{\"filename\", \"erro\"}, ...]}`.\nValidation (type/size/count) is all-or-nothing and happens BEFORE any write,\nso a rejected file leaves nothing in S3; `failed` only carries per-file S3\nerrors that occur mid-write.","operationId":"upload_assets_api_assets_upload_post","parameters":[{"name":"prefix","in":"query","required":false,"schema":{"type":"string","description":"Folder prefix to upload into (relative, must start with 'assets')","default":"assets","title":"Prefix"},"description":"Folder prefix to upload into (relative, must start with 'assets')"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_assets_api_assets_upload_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upload Assets Api Assets Upload Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assets/list":{"get":{"tags":["Assets - Admin"],"summary":"List uploaded assets","description":"List files and subfolders under a given S3 prefix (STAGING).","operationId":"list_assets_api_assets_list_get","parameters":[{"name":"prefix","in":"query","required":false,"schema":{"type":"string","description":"Folder prefix to list","default":"assets","title":"Prefix"},"description":"Folder prefix to list"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assets/delete":{"delete":{"tags":["Assets - Admin"],"summary":"Delete a file from S3","description":"Delete a specific asset from S3 (STAGING).","operationId":"delete_asset_api_assets_delete_delete","parameters":[{"name":"key","in":"query","required":true,"schema":{"type":"string","title":"Key"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assets/folder":{"post":{"tags":["Assets - Admin"],"summary":"Create a folder in S3","description":"Create a folder in S3 (STAGING).\n\nNote: S3 doesn't have real folders, but we create a zero-byte object ending with '/'\nto simulate folder structure for listing purposes.","operationId":"create_folder_api_assets_folder_post","parameters":[{"name":"folder_path","in":"query","required":true,"schema":{"type":"string","description":"Folder path to create (relative to assets/)","title":"Folder Path"},"description":"Folder path to create (relative to assets/)"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Assets - Admin"],"summary":"Delete a folder and all its contents from S3","description":"Delete a folder and everything under it (STAGING). Recursive and irreversible.\n\nThe frontend picker has always called this route; it simply did not exist\n(only `POST /assets/folder` did), so \"Eliminar pasta\" was 405-ing.\n\nPlain `def`, not `async def`: this walks an unbounded prefix and issues\nblocking boto3 calls, which on the event loop would starve every other\nrequest (docs/claude/10-api-patterns.md). FastAPI runs `def` in a threadpool.","operationId":"delete_folder_api_assets_folder_delete","parameters":[{"name":"folder_path","in":"query","required":true,"schema":{"type":"string","description":"Folder path to delete (relative to assets/)","title":"Folder Path"},"description":"Folder path to delete (relative to assets/)"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Folder Api Assets Folder Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assets/bulk-delete":{"post":{"tags":["Assets - Admin"],"summary":"Delete several files from S3 in one request","description":"Delete many files in ONE request. Body: `{\"keys\": [...]}`.\n\nBatched server-side rather than looped client-side: the single-key routes are\n`async def` running blocking boto3, so N concurrent client calls would put N\nblocking round-trips on the shared event loop.\n\nReturns `{\"deleted\": n, \"results\": [{\"key\", \"status\", \"erro\"?}, ...]}` —\n`status` is `deleted` | `invalid` | `error`. S3 reports success for a key\nthat never existed, so `deleted` means \"no longer present\".","operationId":"bulk_delete_assets_api_assets_bulk_delete_post","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bulk Delete Assets Api Assets Bulk Delete Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assets/bulk-move":{"post":{"tags":["Assets - Admin"],"summary":"Move several files into a folder in one request","description":"Move many files into one destination folder. Body:\n`{\"sources\": [\"<rel path>\", ...], \"destination\": \"<rel folder>\"}`\n(both relative to `assets/`; an empty destination means the `assets/` root).\n\n⚠️ Unlike `POST /assets/move`, this route **never overwrites**: the\ndestination is probed with `head_object` first and a collision is reported,\nnot silently clobbered. `copy_object` has no if-none-match, so this is a\ncheck-then-act — the window is small but real; two tabs moving the same\nfilename concurrently can still lose one. It is strictly safer than the\nunconditional copy, not a lock.\n\nReturns `{\"moved\": n, \"results\": [{\"source\", \"status\", \"erro\"?}, ...]}` with\n`status` in `moved` | `collision` | `source_missing` | `same_location` |\n`invalid` | `error`.","operationId":"bulk_move_assets_api_assets_bulk_move_post","parameters":[{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bulk Move Assets Api Assets Bulk Move Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assets/move":{"post":{"tags":["Assets - Admin"],"summary":"Move/rename a file or folder in S3","description":"Move or rename a file or folder in S3 (STAGING).\n\n- For folders, all contents are moved recursively\n- Source path is deleted after successful copy","operationId":"move_asset_api_assets_move_post","parameters":[{"name":"source","in":"query","required":true,"schema":{"type":"string","description":"Source path (relative to assets/)","title":"Source"},"description":"Source path (relative to assets/)"},{"name":"destination","in":"query","required":true,"schema":{"type":"string","description":"Destination path (relative to assets/)","title":"Destination"},"description":"Destination path (relative to assets/)"},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/faturas/search":{"get":{"tags":["Faturas - Admin"],"summary":"Search invoices for reconciliation","description":"Search invoices (faturas) for reconciliation, scoped to the POS/company of the\nbank movement being reconciled — NOT to the logged-in user's own POS.\n\nDefaults to the movement's own store and widens to the whole company on\nrequest: the match is nearly always in the same store, but group-level\npayments do cross stores, and before this the wider set was unreachable.\n\nReturns {\"results\", \"total\", \"truncated\", \"window\", \"scope\", \"warning\"} —\nevery narrowing is echoed back, because a silently applied filter is what made\nthe original bug invisible.","operationId":"search_faturas_for_user_api_faturas_search_get","parameters":[{"name":"bank_id","in":"query","required":true,"schema":{"type":"integer","description":"Bank movement being reconciled","title":"Bank Id"},"description":"Bank movement being reconciled"},{"name":"type","in":"query","required":false,"schema":{"type":"string","default":"todas","title":"Type"}},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date"}},{"name":"query","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Query"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","pattern":"^(pv|company)$","description":"'pv' = the movement's own store (default), 'company' = every store","default":"pv","title":"Scope"},"description":"'pv' = the movement's own store (default), 'company' = every store"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search Faturas For User Api Faturas Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/faturas/reconciled":{"get":{"tags":["Faturas - Admin"],"summary":"Get reconciled invoices","description":"Reconciled invoices for the POS of the bank movement being reconciled.\n\nPreviously this took no parameter at all and resolved the POS from the caller's\nZ_Users.idpointofsale, so the \"Faturas Conciliadas\" tab showed a different\nstore's list than the movement on screen — hiding the one piece of information\nthat explains why an invoice is missing from the selectable list.\nFalls back to the caller's own POS when no bank_id is supplied.","operationId":"reconciled_faturas_for_user_api_faturas_reconciled_get","parameters":[{"name":"bank_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Bank movement being reconciled — scopes the list to its POS","title":"Bank Id"},"description":"Bank movement being reconciled — scopes the list to its POS"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/email/send":{"post":{"tags":["Email - Admin"],"summary":"Send email with attachments","description":"Sends an email using the system's SMTP settings.\nAuthenticated users only.","operationId":"send_email_with_attachments_api_email_send_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_send_email_with_attachments_api_email_send_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/emails":{"get":{"tags":["Email - Admin"],"summary":"List emails by module","description":"List all email records for a given module + record.","operationId":"list_emails_api_emails_get","parameters":[{"name":"id_modulo","in":"query","required":true,"schema":{"type":"integer","description":"Module ID (e.g. 7=PV, 12=Clients)","title":"Id Modulo"},"description":"Module ID (e.g. 7=PV, 12=Clients)"},{"name":"id_modulo_id","in":"query","required":true,"schema":{"type":"integer","description":"Record ID within the module","title":"Id Modulo Id"},"description":"Record ID within the module"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Email - Admin"],"summary":"Create email record","description":"Create a new email record in the Emails table.","operationId":"create_email_api_emails_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/emails/types":{"get":{"tags":["Email - Admin"],"summary":"Get email types for a module","description":"Get available email types (TipoEmailNomeModulo) for a given module.","operationId":"get_email_types_api_emails_types_get","parameters":[{"name":"id_modulo","in":"query","required":true,"schema":{"type":"integer","description":"Module ID","title":"Id Modulo"},"description":"Module ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/emails/{email_id}":{"put":{"tags":["Email - Admin"],"summary":"Update email record","description":"Update an existing email record.","operationId":"update_email_api_emails__email_id__put","parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"integer","title":"Email Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Email - Admin"],"summary":"Delete email record","description":"Delete an email record.","operationId":"delete_email_api_emails__email_id__delete","parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"integer","title":"Email Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox":{"get":{"tags":["Email - System Admin Inbox"],"summary":"List archived emails for a mailbox","description":"List a mailbox.\n\n`folder` now carries a validation pattern — an unknown value used to return\nan empty list rather than a 400, which is indistinguishable from an empty\nfolder.\n\nBoth `scope` and the widened `search` default to the previous behaviour, so\nthis endpoint can ship before the frontend that uses them.","operationId":"list_inbox_api_system_admin_inbox_get","parameters":[{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","description":"Mailbox key","default":"info","title":"Mailbox"},"description":"Mailbox key"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Page Size"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Terms AND-ed across subject / from / to / cc / preview","title":"Search"},"description":"Terms AND-ed across subject / from / to / cc / preview"},{"name":"direction","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(in|out)$"},{"type":"null"}],"title":"Direction"}},{"name":"folder","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(inbox|archived|trash|spam|drafts)$"},{"type":"null"}],"title":"Folder"}},{"name":"starred_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Starred Only"}},{"name":"unread_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Unread Only"}},{"name":"has_attachments_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Has Attachments Only"}},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Since"}},{"name":"label_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Label Id"}},{"name":"group_by_thread","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Group By Thread"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","pattern":"^(folder|all)$","description":"'folder' (default) honours folder+direction; 'all' searches every folder except trash/spam.","default":"folder","title":"Scope"},"description":"'folder' (default) honours folder+direction; 'all' searches every folder except trash/spam."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/counts":{"get":{"tags":["Email - System Admin Inbox"],"summary":"Per-folder message + unread counts","description":"Folder badges for the sidebar.\n\nRegistered BEFORE the greedy `/{message_db_id}` route at the bottom of this\nmodule — that one is a catch-all and would otherwise swallow `/counts` and\ntry to parse it as an int.","operationId":"inbox_counts_api_system_admin_inbox_counts_get","parameters":[{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","description":"Mailbox key","default":"info","title":"Mailbox"},"description":"Mailbox key"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/mailboxes":{"get":{"tags":["Email - System Admin Inbox"],"summary":"List mailboxes the current user can access","description":"Return the inboxes available in the switcher, sourced from Z_Mailboxes.\n\nPhase 3 (system_admin route): returns EVERY mailbox in the registry.\nPhase 4 will narrow by `current_user.idcompany`/`idpointofsale` once\nper-PV inboxes ship — the DB function already accepts those filters.","operationId":"list_mailboxes_api_system_admin_inbox_mailboxes_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Email - System Admin Inbox"],"summary":"Create a new mailbox on a verified domain","operationId":"create_mailbox_route_api_system_admin_inbox_mailboxes_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/signature":{"get":{"tags":["Email - System Admin Inbox"],"summary":"Get the current user's mail signature","operationId":"get_user_signature_api_system_admin_inbox_signature_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Email - System Admin Inbox"],"summary":"Update the current user's mail signature","operationId":"put_user_signature_api_system_admin_inbox_signature_put","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/send":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Compose and send an email from the mailbox","description":"Send a new email from the mailbox's outbound address.\n\nReply: pass `in_reply_to=<original-message-id>`. Forward: just pre-fill\nsubject/body on the client; the message is treated as a normal new send.\nThe sent .eml is archived in the same mailbox with direction='out' so it\nshows up under the Sent filter on the listing endpoint.","operationId":"send_inbox_email_api_system_admin_inbox_send_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_send_inbox_email_api_system_admin_inbox_send_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/move":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Bulk move messages between folders","operationId":"move_inbox_api_system_admin_inbox_move_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/star":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Bulk star/unstar messages","operationId":"star_inbox_api_system_admin_inbox_star_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/read":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Bulk mark messages as read/unread","operationId":"read_inbox_api_system_admin_inbox_read_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/messages/{message_db_id}":{"delete":{"tags":["Email - System Admin Inbox"],"summary":"Permanently delete a message (only from Trash/Spam)","operationId":"hard_delete_inbox_api_system_admin_inbox_messages__message_db_id__delete","parameters":[{"name":"message_db_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Db Id"}},{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/threads/{thread_id}":{"get":{"tags":["Email - System Admin Inbox"],"summary":"Get all messages in a thread","description":"Fetch a conversation.\n\nCapped at MAX_THREAD_MESSAGES. Bodies live only in S3, so every message in\nthe response costs a GET; `include_bodies` defaults to \"all\" purely for\nbackward compatibility with the current frontend.","operationId":"get_thread_api_system_admin_inbox_threads__thread_id__get","parameters":[{"name":"thread_id","in":"path","required":true,"schema":{"type":"string","title":"Thread Id"}},{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"include_bodies","in":"query","required":false,"schema":{"type":"string","pattern":"^(none|latest|all)$","description":"Which message bodies to fetch from S3. 'latest' lets the client lazy-load the rest through GET /{id}.","default":"all","title":"Include Bodies"},"description":"Which message bodies to fetch from S3. 'latest' lets the client lazy-load the rest through GET /{id}."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/drafts":{"get":{"tags":["Email - System Admin Inbox"],"summary":"List the current user's drafts","operationId":"list_drafts_api_system_admin_inbox_drafts_get","parameters":[{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Email - System Admin Inbox"],"summary":"Create a new empty draft","operationId":"create_draft_api_system_admin_inbox_drafts_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/drafts/{draft_id}":{"get":{"tags":["Email - System Admin Inbox"],"summary":"Get a single draft","operationId":"get_draft_api_system_admin_inbox_drafts__draft_id__get","parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"integer","title":"Draft Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Email - System Admin Inbox"],"summary":"Partial update / autosave","operationId":"update_draft_api_system_admin_inbox_drafts__draft_id__put","parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"integer","title":"Draft Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Email - System Admin Inbox"],"summary":"Discard a draft","operationId":"delete_draft_api_system_admin_inbox_drafts__draft_id__delete","parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"integer","title":"Draft Id"}},{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/drafts/{draft_id}/attachments":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Upload one attachment to a draft","operationId":"upload_draft_attachment_api_system_admin_inbox_drafts__draft_id__attachments_post","parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"integer","title":"Draft Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_draft_attachment_api_system_admin_inbox_drafts__draft_id__attachments_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/drafts/{draft_id}/attachments/{attachment_index}":{"delete":{"tags":["Email - System Admin Inbox"],"summary":"Remove a single draft attachment","operationId":"delete_draft_attachment_api_system_admin_inbox_drafts__draft_id__attachments__attachment_index__delete","parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"integer","title":"Draft Id"}},{"name":"attachment_index","in":"path","required":true,"schema":{"type":"integer","title":"Attachment Index"}},{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/drafts/{draft_id}/send":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Promote draft → outbound .eml + archive","operationId":"send_draft_api_system_admin_inbox_drafts__draft_id__send_post","parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"integer","title":"Draft Id"}},{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"apply_signature","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Apply Signature"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/labels":{"get":{"tags":["Email - System Admin Inbox"],"summary":"List labels for a mailbox","operationId":"list_labels_api_system_admin_inbox_labels_get","parameters":[{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Email - System Admin Inbox"],"summary":"Create a label","operationId":"create_label_api_system_admin_inbox_labels_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/labels/{label_id}":{"put":{"tags":["Email - System Admin Inbox"],"summary":"Update label name/color","operationId":"update_label_api_system_admin_inbox_labels__label_id__put","parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"integer","title":"Label Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Email - System Admin Inbox"],"summary":"Delete a label","operationId":"delete_label_api_system_admin_inbox_labels__label_id__delete","parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"integer","title":"Label Id"}},{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/labels/attach":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Attach labels to messages (bulk)","operationId":"attach_labels_api_system_admin_inbox_labels_attach_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/labels/detach":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Detach labels from messages (bulk)","operationId":"detach_labels_api_system_admin_inbox_labels_detach_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/domains":{"get":{"tags":["Email - System Admin Inbox"],"summary":"List every SES-verified domain","operationId":"list_domains_api_system_admin_inbox_domains_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Email - System Admin Inbox"],"summary":"Register a new domain in SES","operationId":"add_domain_api_system_admin_inbox_domains_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/domains/{domain_id}/recheck":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Re-poll SES for status","operationId":"recheck_domain_api_system_admin_inbox_domains__domain_id__recheck_post","parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"integer","title":"Domain Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/domains/{domain_id}":{"delete":{"tags":["Email - System Admin Inbox"],"summary":"Remove SES identity + DB row","operationId":"delete_domain_api_system_admin_inbox_domains__domain_id__delete","parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"integer","title":"Domain Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/mailboxes/{mailbox_id}":{"delete":{"tags":["Email - System Admin Inbox"],"summary":"Delete a mailbox","operationId":"delete_mailbox_route_api_system_admin_inbox_mailboxes__mailbox_id__delete","parameters":[{"name":"mailbox_id","in":"path","required":true,"schema":{"type":"integer","title":"Mailbox Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/rules":{"get":{"tags":["Email - System Admin Inbox"],"summary":"List inbox rules for a mailbox","operationId":"list_inbox_rules_api_system_admin_inbox_rules_get","parameters":[{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"enabled_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Enabled Only"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Email - System Admin Inbox"],"summary":"Create a new inbox rule","operationId":"create_inbox_rule_api_system_admin_inbox_rules_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/rules/{rule_id}":{"put":{"tags":["Email - System Admin Inbox"],"summary":"Update an inbox rule","operationId":"update_inbox_rule_api_system_admin_inbox_rules__rule_id__put","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"integer","title":"Rule Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Email - System Admin Inbox"],"summary":"Delete an inbox rule","operationId":"delete_inbox_rule_api_system_admin_inbox_rules__rule_id__delete","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"integer","title":"Rule Id"}},{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/rules/reorder":{"post":{"tags":["Email - System Admin Inbox"],"summary":"Reorder rules by priority","operationId":"reorder_inbox_rules_api_system_admin_inbox_rules_reorder_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/{message_db_id}":{"get":{"tags":["Email - System Admin Inbox"],"summary":"Get full archived email","operationId":"get_inbox_message_api_system_admin_inbox__message_db_id__get","parameters":[{"name":"message_db_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Db Id"}},{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-admin/inbox/{message_db_id}/attachments/{filename}":{"get":{"tags":["Email - System Admin Inbox"],"summary":"Download an attachment","operationId":"get_inbox_attachment_api_system_admin_inbox__message_db_id__attachments__filename__get","parameters":[{"name":"message_db_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Db Id"}},{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}},{"name":"mailbox","in":"query","required":false,"schema":{"type":"string","default":"info","title":"Mailbox"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/configs/tracking/{domain}":{"post":{"tags":["Configs - Admin"],"summary":"Update tracking config JSON","description":"Uploads or replaces the tracking configuration JSON file.","operationId":"set_tracking_config_api_configs_tracking__domain__post","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Config"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/configs/header/{domain}":{"post":{"tags":["Configs - Admin"],"summary":"Update header HTML","description":"Uploads or replaces the header HTML content.","operationId":"set_page_header_api_configs_header__domain__post","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_set_page_header_api_configs_header__domain__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/configs/body/{domain}":{"post":{"tags":["Configs - Admin"],"summary":"Update body HTML","description":"Uploads or replaces the body HTML content.","operationId":"set_page_body_api_configs_body__domain__post","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_set_page_body_api_configs_body__domain__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements":{"get":{"tags":["Financeiro (Protected)"],"summary":"List Movements","description":"Listar movimentos pagos com filtros opcionais.","operationId":"list_movements_api_financeiro_movements_get","parameters":[{"name":"date_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Start"}},{"name":"date_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date End"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"}},{"name":"rubrica","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rubrica"}},{"name":"metodo_pagamento","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Metodo Pagamento"}},{"name":"matricula","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Matricula"}},{"name":"cliente","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cliente"}},{"name":"socio","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by Socio ID (only movements present in MovimentosSocios)","title":"Socio"},"description":"Filter by Socio ID (only movements present in MovimentosSocios)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"tipo","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by type: 'entrada' (positive) or 'saida' (negative)","title":"Tipo"},"description":"Filter by type: 'entrada' (positive) or 'saida' (negative)"},{"name":"totalvalor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by ValorTotal match (accepts comma or dot as decimal separator)","title":"Totalvalor"},"description":"Filter by ValorTotal match (accepts comma or dot as decimal separator)"},{"name":"cost_center","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: 'parent' = show only cost-center parent movements","title":"Cost Center"},"description":"Filter: 'parent' = show only cost-center parent movements"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Movements Api Financeiro Movements Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/pending":{"get":{"tags":["Financeiro (Protected)"],"summary":"Movimentos pendentes do PV do utilizador — a receber e a pagar","description":"Imagem completa dos movimentos pendentes do PV do utilizador, nos dois\nsentidos (a receber / a pagar). Inclui movimentos regulares (selecionáveis)\ne divisões de centro de custo (apenas informativas).\n\ndate_start/date_end filtram o período sobre DataRegisto (todas as linhas\npendentes estão por pagar → sem DataPagamento).","operationId":"get_pending_movements_api_financeiro_movements_pending_get","parameters":[{"name":"date_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Period filter start (YYYY-MM-DD)","title":"Date Start"},"description":"Period filter start (YYYY-MM-DD)"},{"name":"date_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Period filter end, inclusive (YYYY-MM-DD)","title":"Date End"},"description":"Period filter end, inclusive (YYYY-MM-DD)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Pending Movements Api Financeiro Movements Pending Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/deleted":{"get":{"tags":["Financeiro (Protected)"],"summary":"Listar movimentos eliminados (reconstruídos do snapshot de auditoria)","description":"Movimentos eliminados da empresa, reconstruídos a partir do snapshot de\nauditoria (HistoricoActions). Apenas leitura — os movimentos já não existem\nna tabela Movimentos. Linhas eliminadas antes da funcionalidade de snapshot\nnão têm detalhe (has_snapshot=False).","operationId":"list_deleted_movements_route_api_financeiro_movements_deleted_get","parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Deleted Movements Route Api Financeiro Movements Deleted Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/{movement_id}":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter detalhes do movimento","description":"Obter detalhes completos de um movimento.","operationId":"get_movement_api_financeiro_movements__movement_id__get","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovimentoDetailedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Financeiro (Protected)"],"summary":"Atualizar movimento","description":"Atualizar dados de um movimento existente.","operationId":"update_movement_api_financeiro_movements__movement_id__put","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovimentoUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovimentoDetailedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Financeiro (Protected)"],"summary":"Eliminar movimento","description":"Eliminar um movimento.","operationId":"delete_movement_api_financeiro_movements__movement_id__delete","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/{movement_id}/history":{"get":{"tags":["Financeiro (Protected)"],"summary":"Histórico de auditoria de um movimento (criado/alterado/eliminado)","description":"Linha do tempo de auditoria do movimento, com autor, data e estado anterior\nde cada alteração. Funciona para movimentos vivos e já eliminados.","operationId":"get_movement_history_api_financeiro_movements__movement_id__history_get","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Movement History Api Financeiro Movements  Movement Id  History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/cash-summary":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter resumo de caixa","description":"Obter resumo de caixa do ponto de venda.","operationId":"get_cash_summary_api_financeiro_cash_summary_get","parameters":[{"name":"since_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since Date"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/search":{"get":{"tags":["Financeiro (Protected)"],"summary":"Pesquisar movimentos","description":"Pesquisar movimentos por termo.","operationId":"search_movements_api_financeiro_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"title":"Q"}},{"name":"paid_only","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Paid Only"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovimentoSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/rubricas":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter categorias de despesa","description":"Obter lista de rubricas para dropdown.","operationId":"get_rubricas_api_financeiro_rubricas_get","parameters":[{"name":"car_related","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Car Related"}},{"name":"fluxo_positivo","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fluxo Positivo"}},{"name":"exclude_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Exclude Id"}},{"name":"not_car_related","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Not Car Related"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RubricaSelectResponse"},"title":"Response Get Rubricas Api Financeiro Rubricas Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/payment-methods":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter métodos de pagamento","description":"Obter lista de métodos de pagamento do ponto de venda.","operationId":"get_payment_methods_api_financeiro_payment_methods_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PaymentMethodSelectResponse"},"title":"Response Get Payment Methods Api Financeiro Payment Methods Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/suppliers":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter fornecedores","description":"Obter lista de fornecedores da empresa.","operationId":"get_suppliers_api_financeiro_suppliers_get","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SupplierSelectResponse"},"title":"Response Get Suppliers Api Financeiro Suppliers Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/supplier-by-nif/{nif}":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter fornecedor por NIF de fatura","description":"Look up the most recent fornecedor used in Movimentos for a given invoice emitter NIF.\n\nAccepts both Portuguese 9-digit NIFs and foreign alphanumeric VAT IDs\n(Faturas.A is nvarchar).","operationId":"get_supplier_by_nif_api_financeiro_supplier_by_nif__nif__get","parameters":[{"name":"nif","in":"path","required":true,"schema":{"type":"string","title":"Nif"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/vehicles":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter veículos","description":"Obter lista de veículos da empresa.\n\nPlain `def`, NOT `async def`: the body is a blocking pyodbc query, which on\nthe event loop stalls every other request on this worker (the 2026-07-08\nreconnect-herd incident — docs/claude/10-api-patterns.md, and the same note\non routes/toc.py::create_invoice). FastAPI runs `def` handlers in a\nthreadpool. This became load-bearing when the invoice dialog started calling\nit per keystroke instead of once per open.","operationId":"get_vehicles_api_financeiro_vehicles_get","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VehicleSelectResponse"},"title":"Response Get Vehicles Api Financeiro Vehicles Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/partners/active":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter parceiros ativos","description":"Obter parceiros com parcerias ativas no ponto de venda atual.","operationId":"get_active_partners_api_financeiro_partners_active_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/socios":{"get":{"tags":["Financeiro (Protected)"],"summary":"Listar sócios da empresa","description":"Listar sócios do ponto de venda atual — usado para dropdowns de filtro.","operationId":"list_socios_api_financeiro_socios_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/cost":{"post":{"tags":["Financeiro (Protected)"],"summary":"Criar movimento de custo","description":"Criar um movimento de custo.\n\nO campo lucro é determinado automaticamente pelo estado do veículo.","operationId":"create_cost_movement_api_financeiro_movements_cost_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovimentoCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovimentoDetailedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/profit":{"post":{"tags":["Financeiro (Protected)"],"summary":"Criar movimento de receita","description":"Criar um movimento de receita.\n\nO campo lucro é definido como 1 por defeito.","operationId":"create_profit_movement_api_financeiro_movements_profit_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovimentoCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovimentoDetailedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/partner":{"post":{"tags":["Financeiro (Protected)"],"summary":"Criar movimento de parceiro","description":"Criar um movimento associado a um parceiro.","operationId":"create_partner_movement_api_financeiro_movements_partner_post","parameters":[{"name":"partner_id","in":"query","required":true,"schema":{"type":"integer","description":"ID do parceiro","title":"Partner Id"},"description":"ID do parceiro"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerMovimentoCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovimentoDetailedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/payment-method/{metodo_id}":{"get":{"tags":["Financeiro (Protected)"],"summary":"Listar movimentos por método de pagamento","description":"Listar movimentos filtrados por método de pagamento.","operationId":"list_by_payment_method_api_financeiro_payment_method__metodo_id__get","parameters":[{"name":"metodo_id","in":"path","required":true,"schema":{"type":"integer","title":"Metodo Id"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MovimentoListResponse"},"title":"Response List By Payment Method Api Financeiro Payment Method  Metodo Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/partner/{partner_id}":{"get":{"tags":["Financeiro (Protected)"],"summary":"Listar movimentos de parceiro","description":"Listar movimentos associados a um parceiro (filtro de período sobre DataRegisto).","operationId":"list_partner_movements_api_financeiro_partner__partner_id__get","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","title":"Partner Id"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"date_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Period filter start (YYYY-MM-DD)","title":"Date Start"},"description":"Period filter start (YYYY-MM-DD)"},{"name":"date_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Period filter end, inclusive (YYYY-MM-DD)","title":"Date End"},"description":"Period filter end, inclusive (YYYY-MM-DD)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MovimentoListResponse"},"title":"Response List Partner Movements Api Financeiro Partner  Partner Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/transfer":{"post":{"tags":["Financeiro (Protected)"],"summary":"Transferir entre métodos de pagamento","description":"Transferir valor entre dois métodos de pagamento.\n\nCria dois movimentos: um negativo na origem e um positivo no destino.","operationId":"transfer_between_payment_methods_api_financeiro_movements_transfer_post","parameters":[{"name":"valor","in":"query","required":true,"schema":{"type":"number","exclusiveMinimum":0,"description":"Valor a transferir","title":"Valor"},"description":"Valor a transferir"},{"name":"metodo_origem","in":"query","required":true,"schema":{"type":"integer","description":"ID do método de origem","title":"Metodo Origem"},"description":"ID do método de origem"},{"name":"metodo_destino","in":"query","required":true,"schema":{"type":"integer","description":"ID do método de destino","title":"Metodo Destino"},"description":"ID do método de destino"},{"name":"descricao","in":"query","required":false,"schema":{"type":"string","description":"Descrição do movimento","default":"Transferência entre métodos de pagamento","title":"Descricao"},"description":"Descrição do movimento"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/mark-paid":{"post":{"tags":["Financeiro (Protected)"],"summary":"Marcar movimentos como pagos","description":"Marcar múltiplos movimentos como pagos.","operationId":"mark_paid_api_financeiro_mark_paid_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/duplicate-check":{"post":{"tags":["Financeiro (Protected)"],"summary":"Registar a apresentação/escolha do aviso de movimento duplicado","description":"Instrumentação do aviso mostrado ao inserir um movimento semelhante a um\njá existente por pagar. Sem efeitos no negócio — só escreve auditoria.\n\n`def`, não `async def`: a escrita é pyodbc síncrono e bloquearia o event loop\n(ver docs/claude/10-api-patterns.md).","operationId":"log_duplicate_check_api_financeiro_movements_duplicate_check_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateCheckLogRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/comprovativo-batch":{"post":{"tags":["Financeiro (Protected)"],"summary":"Associar UM comprovativo de pagamento a vários movimentos","description":"Batch \"por pagar → pago\": anexa UM ficheiro (armazenado uma única vez em\nS3) a todos os movimentos elegíveis do mesmo fornecedor. Movimentos sem\nfatura, já com comprovativo, de outro PV/empresa ou sem fornecedor são\ndevolvidos em `skipped` com o motivo.","operationId":"attach_comprovativo_batch_api_financeiro_movements_comprovativo_batch_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_attach_comprovativo_batch_api_financeiro_movements_comprovativo_batch_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComprovativoBatchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/cost-center":{"post":{"tags":["Financeiro (Protected)"],"summary":"Criar movimento com divisão por centros de custo","description":"Create a cost movement split across multiple PVs as cost centers.","operationId":"create_cost_center_movement_api_financeiro_movements_cost_center_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostCenterMovimentoCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/{movement_id}/settle-partial":{"post":{"tags":["Financeiro (Protected)"],"summary":"Liquidar parcialmente um movimento pendente","description":"Settle part of a pending movement.\n\nThe whole concurrency story is one guarded UPDATE in the DB layer — see\ndb/financials.py::settle_movement_partially. A losing race returns 409, not\na silent double-settlement.\n\nPlain `def` — synchronous pyodbc must not run on the event loop.","operationId":"settle_movement_partially_api_financeiro_movements__movement_id__settle_partial_post","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartialSettlementRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/{movement_id}/transfer-pv":{"post":{"tags":["Financeiro (Protected)"],"summary":"Transferir um movimento por pagar para outro ponto de venda","description":"Give an unpaid movement away to another point of sale of the same company.\n\nPUSH by the owning PV — a store cannot pull another store's movement. The\nownership predicate lives in the DB UPDATE's WHERE (compare-and-swap), so a\nlosing race returns 409 rather than silently moving the wrong row.\n\nPlain `def` — synchronous pyodbc must not run on the event loop.","operationId":"transfer_movement_point_of_sale_api_financeiro_movements__movement_id__transfer_pv_post","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementTransferPvRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/{movement_id}/invoices":{"get":{"tags":["Financeiro (Protected)"],"summary":"Faturas associadas a um movimento","description":"Invoice set linked to a movement, with per-link allocation.\n\nPlain `def` — synchronous pyodbc must not run on the event loop.","operationId":"get_movement_invoices_api_financeiro_movements__movement_id__invoices_get","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Financeiro (Protected)"],"summary":"Definir as faturas associadas a um movimento","description":"Replace the whole invoice set for a movement.\n\nA set-REPLACE, not add/remove: the dialog edits the set as a unit, and a\nreplace is idempotent under a double-submit, so a retry cannot\ndouble-allocate. Over-allocation (per invoice and per movement) is refused\nin the DB layer inside the same transaction that writes.","operationId":"set_movement_invoices_api_financeiro_movements__movement_id__invoices_put","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementInvoicesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/{movement_id}/cost-center-splits":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter detalhes de divisão por centro de custo","description":"Get cost center split details for a parent movement.\n\nPlain `def` (not `async`): the lookup below is synchronous pyodbc and would\nblock the shared event loop for every concurrent request.","operationId":"get_cost_center_splits_api_financeiro_movements__movement_id__cost_center_splits_get","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CostCenterSplitDetail"},"title":"Response Get Cost Center Splits Api Financeiro Movements  Movement Id  Cost Center Splits Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Financeiro (Protected)"],"summary":"Atualizar divisão por centro de custo","description":"Update cost center split values. Only origin PV user can do this.","operationId":"update_cost_center_splits_api_financeiro_movements__movement_id__cost_center_splits_put","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostCenterSplitsUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CostCenterSplitDetail"},"title":"Response Update Cost Center Splits Api Financeiro Movements  Movement Id  Cost Center Splits Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/{movement_id}/invoice-split-status":{"get":{"tags":["Financeiro (Protected)"],"summary":"Saber se a fatura do movimento de centro de custo ainda não foi dividida","description":"Report the state of the invoice split attached to this cost-center\nmovement, so the UI can confirm what happened (the split is now done\nautomatically) or offer to create one that is still missing.\n\nReturns {invoice_split_missing, invoice_id, state, splits, warnings,\ncan_split}. `state` is one of: no_invoice | split | manual | missing.","operationId":"get_invoice_split_status_api_financeiro_movements__movement_id__invoice_split_status_get","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/{movement_id}/sync-invoice-split":{"post":{"tags":["Financeiro (Protected)"],"summary":"Dividir a fatura do movimento de acordo com o centro de custo","description":"Mirror this cost-center movement's split onto its attached invoice\n(Z_InvoicesCostCenter) so the dashboard 'IVA Deduzido' divides the IVA.\n\nOnly the origin PV of the parent movement may trigger it — the same rule as\nediting the movement split itself. Idempotent: recomputing produces the same\nrows.\n\n`?force=true` makes it an explicit recompute request: it lifts a suppression\n(a split the user previously removed on the fatura) and replaces a\npre-migration split. It still refuses to overwrite one entered by hand in\nthe invoice UI — that one is only editable where it was made.","operationId":"sync_invoice_split_api_financeiro_movements__movement_id__sync_invoice_split_post","parameters":[{"name":"movement_id","in":"path","required":true,"schema":{"type":"integer","title":"Movement Id"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/cost-center-deletions/{deletion_id}/resend":{"post":{"tags":["Financeiro (Protected)"],"summary":"Reenviar notificações de eliminação de centro de custo","description":"Re-send the destination-PV warning emails for a past cascade deletion.\n\nOnly the origin PV / company that performed the deletion may re-send;\nownership is re-validated at the service + DB layers.","operationId":"resend_cost_center_deletion_emails_api_financeiro_cost_center_deletions__deletion_id__resend_post","parameters":[{"name":"deletion_id","in":"path","required":true,"schema":{"type":"integer","title":"Deletion Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/unpaid":{"get":{"tags":["Financeiro (Protected)"],"summary":"Listar movimentos não pagos","description":"Listar movimentos pendentes de pagamento.","operationId":"get_unpaid_movements_api_financeiro_unpaid_get","parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MovimentoListResponse"},"title":"Response Get Unpaid Movements Api Financeiro Unpaid Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/suppliers-to-pay":{"get":{"tags":["Financeiro (Protected)"],"summary":"Obter fornecedores com saldos pendentes","description":"Obter lista de fornecedores com valores por pagar.","operationId":"get_suppliers_to_pay_api_financeiro_suppliers_to_pay_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SupplierPayResponse"},"title":"Response Get Suppliers To Pay Api Financeiro Suppliers To Pay Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/clientes/by-iban":{"get":{"tags":["Financeiro (Protected)"],"summary":"Encontrar colaborador por IBAN","description":"Pesquisar colaborador pelo IBAN para importação de salários.","operationId":"get_cliente_by_iban_api_financeiro_clientes_by_iban_get","parameters":[{"name":"iban","in":"query","required":true,"schema":{"type":"string","description":"IBAN a pesquisar","title":"Iban"},"description":"IBAN a pesquisar"},{"name":"type","in":"query","required":false,"schema":{"type":"string","description":"'regular' (IBAN) ou 'alimentar' (IBANAlimentar)","default":"regular","title":"Type"},"description":"'regular' (IBAN) ou 'alimentar' (IBANAlimentar)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClienteByIbanResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financeiro/movements/salary-import":{"post":{"tags":["Financeiro (Protected)"],"summary":"Importar movimentos de salário em lote","description":"Importar movimentos de salário a partir de dados SEPA XML.\n\nCada movimento deve ter:\n- valor_total: float negativo (despesa)\n- colaborador_id: Cliente.ID\n- rubrica_id: por defeito 27\n- lucro: por defeito True\n- descricao: 'Salário' ou 'Subsídio de Alimentação'\n- data_pagamento: data de pagamento do XML","operationId":"import_salary_movements_api_financeiro_movements_salary_import_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalaryImportRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalaryImportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financials/data/regime-iva":{"get":{"tags":["Financials Protected Router"],"summary":"Get Regime Iva","description":"Obter todos os regimes de IVA.","operationId":"get_regime_iva_api_financials_data_regime_iva_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financials/data/regime-iva-vehicles":{"get":{"tags":["Financials Protected Router"],"summary":"Get Regime Iva Vehicles","description":"Obter regimes de IVA para inserção de viaturas (IDs 3, 13 e 16).","operationId":"get_regime_iva_vehicles_api_financials_data_regime_iva_vehicles_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financials/data/rubricas":{"get":{"tags":["Financials Protected Router"],"summary":"Get Rubricas","description":"Obter todas as categorias de despesa (rubricas).","operationId":"get_rubricas_api_financials_data_rubricas_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financials/data/metodos-pagamento":{"get":{"tags":["Financials Protected Router"],"summary":"Get Metodos Pagamento","description":"Obter métodos de pagamento do ponto de venda.","operationId":"get_metodos_pagamento_api_financials_data_metodos_pagamento_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financials/data/bancos":{"get":{"tags":["Financials Protected Router"],"summary":"Get Bancos","description":"Obter lista de bancos.","operationId":"get_bancos_api_financials_data_bancos_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/financials/data/tipos-documento":{"get":{"tags":["Financials Protected Router"],"summary":"Get Tipos Documento","description":"Obter tipos de documento fiscal.","operationId":"get_tipos_documento_api_financials_data_tipos_documento_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices":{"get":{"tags":["invoices"],"summary":"List invoices","description":"List invoices (faturas) with filters and pagination.\n\nTranslates VBA: PTQ_Financeiro_list","operationId":"list_faturas_api_invoices_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by year","title":"Year"},"description":"Filter by year"},{"name":"month","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by month(s) — CSV of 1-12 (#695 multi)","title":"Month"},"description":"Filter by month(s) — CSV of 1-12 (#695 multi)"},{"name":"tipo_documento","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by document type(s) — CSV (#695 multi)","title":"Tipo Documento"},"description":"Filter by document type(s) — CSV (#695 multi)"},{"name":"enviado_contabilidade","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by sent to accountant","title":"Enviado Contabilidade"},"description":"Filter by sent to accountant"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search in number, ATCUD, emitter/acquirer NIF or client name","title":"Search"},"description":"Search in number, ATCUD, emitter/acquirer NIF or client name"},{"name":"client_nif","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by client NIF(s) (Faturas.A) — CSV (#695 multi)","title":"Client Nif"},"description":"Filter by client NIF(s) (Faturas.A) — CSV (#695 multi)"},{"name":"adquirente_nif","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by acquirer/customer NIF(s) (Faturas.B) — CSV","title":"Adquirente Nif"},"description":"Filter by acquirer/customer NIF(s) (Faturas.B) — CSV"},{"name":"emitido","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Flow filter: 'vendas' (own PV NIF/NIPC) or 'compras'","title":"Emitido"},"description":"Flow filter: 'vendas' (own PV NIF/NIPC) or 'compras'"},{"name":"justification_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"CSV of justified|partially_justified|unjustified|over_justified (#695 multi)","title":"Justification Status"},"description":"CSV of justified|partially_justified|unjustified|over_justified (#695 multi)"},{"name":"payment_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"CSV of paid|partially_paid|unpaid|over_paid (#695 multi)","title":"Payment Status"},"description":"CSV of paid|partially_paid|unpaid|over_paid (#695 multi)"},{"name":"archive_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"CSV of TOConline archive states: enviada|arquivada|erro_arquivo|sem_confirmacao|sem_feedback (#695 multi)","title":"Archive Status"},"description":"CSV of TOConline archive states: enviada|arquivada|erro_arquivo|sem_confirmacao|sem_feedback (#695 multi)"},{"name":"pv","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by PV the invoice belongs to (uploaded OR cost-center split) — CSV of PontosDeVenda.ID","title":"Pv"},"description":"Filter by PV the invoice belongs to (uploaded OR cost-center split) — CSV of PontosDeVenda.ID"},{"name":"has_cost_center","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by presence of a cost-center split (true=has one, false=has none)","title":"Has Cost Center"},"description":"Filter by presence of a cost-center split (true=has one, false=has none)"},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by dataentrada >= this date (YYYY-MM-DD)","title":"Start Date"},"description":"Filter by dataentrada >= this date (YYYY-MM-DD)"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by dataentrada <= this date, inclusive (YYYY-MM-DD)","title":"End Date"},"description":"Filter by dataentrada <= this date, inclusive (YYYY-MM-DD)"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Faturas Api Invoices Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["invoices"],"summary":"Create invoice with file upload","description":"Create a new invoice with optional file upload.\n\nTranslates VBA: UploadInvoice (multipart/form-data)\n\nAccepts both database column names (A, B, F, G, H, etc.) and human-readable\nfield names (emitente_nif, numero, atcud, etc.) from the frontend.","operationId":"create_fatura_api_invoices_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_fatura_api_invoices_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Fatura Api Invoices Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/adquirentes":{"get":{"tags":["invoices"],"summary":"Get adquirentes (customers) for dropdown filter","description":"Distinct acquirers (Faturas.B) that appear in this company's faturas.\n\nThe counterpart to /emitentes. On a sales invoice the emitter is the company\nitself, so an emitter-only filter shows the dealer their own name and nothing\nelse (#764 follow-up). Returns [{nif, nome}], nome falling back to \"NIF: x\"\nwhen the customer is not a registered Cliente.\n\nPlain `def` — synchronous DB work must not run on the event loop.","operationId":"get_adquirentes_api_invoices_adquirentes_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by year","title":"Year"},"description":"Filter by year"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Adquirentes Api Invoices Adquirentes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/emitentes":{"get":{"tags":["invoices"],"summary":"Get emitentes for dropdown filter","description":"Get distinct emitentes (clients) that appear in faturas.\nReturns list of {nif, nome} for dropdown filter.","operationId":"get_emitentes_api_invoices_emitentes_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by year","title":"Year"},"description":"Filter by year"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Emitentes Api Invoices Emitentes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/{fatura_id}":{"get":{"tags":["invoices"],"summary":"Get single invoice","description":"Get a single invoice by ID.\n\nTranslates VBA: PTQ_FinanceiroFicha","operationId":"get_fatura_api_invoices__fatura_id__get","parameters":[{"name":"fatura_id","in":"path","required":true,"schema":{"type":"integer","title":"Fatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Fatura Api Invoices  Fatura Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["invoices"],"summary":"Update invoice","description":"Update an existing invoice.","operationId":"update_fatura_api_invoices__fatura_id__put","parameters":[{"name":"fatura_id","in":"path","required":true,"schema":{"type":"integer","title":"Fatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FaturaUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Fatura Api Invoices  Fatura Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["invoices"],"summary":"Delete invoice","description":"Delete an invoice and associated documents.\n\nTranslates VBA: deletefatura + deleterecord","operationId":"delete_fatura_api_invoices__fatura_id__delete","parameters":[{"name":"fatura_id","in":"path","required":true,"schema":{"type":"integer","title":"Fatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Fatura Api Invoices  Fatura Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/process-qr":{"post":{"tags":["invoices"],"summary":"Process QR code from file","description":"Process a PDF/image file to extract QR code data.\n\nTranslates VBA: Module1.RunQR + ProcessFatura\n\nNOTE: QR reading (PyMuPDF + pyzbar) is CPU-heavy and synchronous.\nWe run it in a thread pool to avoid blocking the asyncio event loop,\nwhich would stall all other requests on this worker.","operationId":"process_qr_api_invoices_process_qr_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_process_qr_api_invoices_process_qr_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QRProcessResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/digitalize-image":{"post":{"tags":["invoices"],"summary":"Clean up a camera photo and return enhanced JPEG bytes","description":"Run the document-digitalization pipeline (perspective correction + CLAHE\n+ unsharp mask) on a camera photo and return the result as a JPEG so the\nfrontend can show it in the preview tile and feed it into the QR reader.\n\nStateless — no DB writes, no S3 writes. PDFs are rejected (the save-side\nflow already handles them). On any CV failure or unsupported input we\nreturn the original bytes so the frontend can stay simple — it always\ngets *some* bytes back.","operationId":"digitalize_image_api_invoices_digitalize_image_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_digitalize_image_api_invoices_digitalize_image_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/{fatura_id}/send-accountant":{"post":{"tags":["invoices"],"summary":"Send invoice to accountant","description":"Send invoice to accountant via email.\n\nTranslates VBA: Module1.SendInvoiceToAcountant","operationId":"send_to_accountant_api_invoices__fatura_id__send_accountant_post","parameters":[{"name":"fatura_id","in":"path","required":true,"schema":{"type":"integer","title":"Fatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__models__invoices__SendEmailResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/{fatura_id}/send-supplier":{"post":{"tags":["invoices"],"summary":"Send invoice to supplier/client","description":"Send invoice to supplier/client via email.\n\nTranslates VBA: Module1.SendInvoiceToSupplier","operationId":"send_to_supplier_api_invoices__fatura_id__send_supplier_post","parameters":[{"name":"fatura_id","in":"path","required":true,"schema":{"type":"integer","title":"Fatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__models__invoices__SendEmailResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/check-nif/{nif}":{"get":{"tags":["invoices"],"summary":"Check if NIF exists in system","description":"Check if a NIF exists in the Cliente table.\n\nTranslates VBA: Checkifnifexists","operationId":"check_nif_api_invoices_check_nif__nif__get","parameters":[{"name":"nif","in":"path","required":true,"schema":{"type":"integer","title":"Nif"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Check Nif Api Invoices Check Nif  Nif  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/{fatura_id}/cost-center":{"post":{"tags":["invoices"],"summary":"Set invoice cost center splits","description":"Set or replace cost center splits for an invoice.\nPercentages are converted to absolute values from ABS(O) and ABS(N).","operationId":"set_invoice_cost_center_api_invoices__fatura_id__cost_center_post","parameters":[{"name":"fatura_id","in":"path","required":true,"schema":{"type":"integer","title":"Fatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceCostCenterSetRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceCostCenterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["invoices"],"summary":"Get invoice cost center splits","description":"Get cost center splits for an invoice.","operationId":"get_invoice_cost_center_api_invoices__fatura_id__cost_center_get","parameters":[{"name":"fatura_id","in":"path","required":true,"schema":{"type":"integer","title":"Fatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceCostCenterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["invoices"],"summary":"Remove invoice cost center splits","description":"Remove all cost center splits for an invoice, and keep them removed.\n\nThe split is now recomputed automatically whenever the cost-center movements\nchange, so removing it has to be recorded — otherwise the next unrelated\nmovement edit would put it straight back.","operationId":"delete_invoice_cost_center_api_invoices__fatura_id__cost_center_delete","parameters":[{"name":"fatura_id","in":"path","required":true,"schema":{"type":"integer","title":"Fatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Invoice Cost Center Api Invoices  Fatura Id  Cost Center Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invoices/{fatura_id}/cost-center/pdf":{"get":{"tags":["invoices"],"summary":"Download invoice PDF with cost center summary page","description":"Download the invoice PDF with an appended cost center summary page.","operationId":"get_invoice_cost_center_pdf_api_invoices__fatura_id__cost_center_pdf_get","parameters":[{"name":"fatura_id","in":"path","required":true,"schema":{"type":"integer","title":"Fatura Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/export/excel":{"post":{"tags":["export"],"summary":"Export module data to Excel","description":"Generate an Excel file with data from the specified module and return a download URL.","operationId":"export_to_excel_api_export_excel_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/export/modules":{"get":{"tags":["export"],"summary":"List available export modules","description":"List all modules that support Excel export.","operationId":"list_export_modules_api_export_modules_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"},"title":"Response List Export Modules Api Export Modules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/export/columns/{module}":{"get":{"tags":["export"],"summary":"Get column configuration for a module","description":"Get the column configuration for a specific module.","operationId":"get_module_columns_api_export_columns__module__get","parameters":[{"name":"module","in":"path","required":true,"schema":{"type":"string","title":"Module"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/blocks":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Blocks","operationId":"protected_get_blocks_api_websites_blocks_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get All Websites","operationId":"protected_get_all_websites_api_websites_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Websites - Protected"],"summary":"Protected Create Website","operationId":"protected_create_website_api_websites_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/orphan-brand":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Orphan Brand","description":"Get the company's brand that has no website yet (for autofill on create).","operationId":"protected_get_orphan_brand_api_websites_orphan_brand_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/domain-available":{"get":{"tags":["Websites - Protected"],"summary":"Protected Domain Available","description":"Whether a domain can be registered, with the same rules the write paths\nenforce. Reasons are the generic guard messages — never another tenant's\ndomain. Pass website_id when editing so the site's own domain reads free.","operationId":"protected_domain_available_api_websites_domain_available_get","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"website_id","in":"query","required":false,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/templates":{"get":{"tags":["Websites - Protected"],"summary":"List Templates","description":"List available website templates (system company, idcompany=0).","operationId":"list_templates_api_websites_templates_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}":{"put":{"tags":["Websites - Protected"],"summary":"Protected Update Website","description":"Update website name and/or domain. If domain changes, migrates S3 content.","operationId":"protected_update_website_api_websites__website_id__put","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Websites - Protected"],"summary":"Protected Delete Website","operationId":"protected_delete_website_api_websites__website_id__delete","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Websites - Protected"],"summary":"Protected Get Website","operationId":"protected_get_website_api_websites__website_id__get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/deploy":{"post":{"tags":["Websites - Protected"],"summary":"Protected Deploy Website","description":"Deploy website to production domain.\n\nCopies all S3 content from staging domain (e.g., rochaautomoveis.multigest.pt)\nto production domain (e.g., rochaautomoveis.pt).\n\n- Staging folder remains intact for future rebuilds\n- Production folder gets overwritten with staging content\n- DB already has production domain references (no DB update needed)","operationId":"protected_deploy_website_api_websites__website_id__deploy_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/suspend":{"post":{"tags":["Websites - Protected"],"summary":"Protected Suspend Website","description":"Deactivate a website so SSR returns a suspended page. Requires system_admin.","operationId":"protected_suspend_website_api_websites__website_id__suspend_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/reactivate":{"post":{"tags":["Websites - Protected"],"summary":"Protected Reactivate Website","description":"Re-enable a previously suspended website. Requires system_admin.","operationId":"protected_reactivate_website_api_websites__website_id__reactivate_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/theme":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Theme","operationId":"protected_get_theme_api_websites__website_id__theme_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Websites - Protected"],"summary":"Update Theme","operationId":"update_theme_api_websites__website_id__theme_put","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/publish-status":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Publish Status","description":"Whether the editor holds changes that were never published to the live site.\n\nThe editor saves to (and reads back from) the staging copy, so a saved\nchange looks applied while visitors still get the production copy — the\ntrap behind ticket #883. The frontend uses this to show \"alterações por\npublicar\" next to Publicar.","operationId":"protected_get_publish_status_api_websites__website_id__publish_status_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/content-types":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Content Types","operationId":"protected_get_content_types_api_websites__website_id__content_types_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Websites - Protected"],"summary":"Protected Create Content Type","operationId":"protected_create_content_type_api_websites__website_id__content_types_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/content-types/{content_type_id}":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Content Type","operationId":"protected_get_content_type_api_websites__website_id__content_types__content_type_id__get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"content_type_id","in":"path","required":true,"schema":{"type":"integer","title":"Content Type Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Websites - Protected"],"summary":"Protected Update Content Type","operationId":"protected_update_content_type_api_websites__website_id__content_types__content_type_id__put","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"content_type_id","in":"path","required":true,"schema":{"type":"integer","title":"Content Type Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Websites - Protected"],"summary":"Protected Delete Content Type","operationId":"protected_delete_content_type_api_websites__website_id__content_types__content_type_id__delete","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"content_type_id","in":"path","required":true,"schema":{"type":"integer","title":"Content Type Id"}},{"name":"delete_pages","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Delete Pages"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Pages","operationId":"protected_get_pages_api_websites__website_id__pages_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"content_type_id","in":"query","required":false,"schema":{"type":"integer","title":"Content Type Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Websites - Protected"],"summary":"Protected Create Page","operationId":"protected_create_page_api_websites__website_id__pages_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/team-audit":{"get":{"tags":["Websites - Protected"],"summary":"Protected Audit Teams In Pages","description":"Scan all pages and return every block that has 'equipa' set.","operationId":"protected_audit_teams_in_pages_api_websites__website_id__pages_team_audit_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/save-teams":{"post":{"tags":["Websites - Protected"],"summary":"Protected Save Teams In Pages","description":"Save equipa changes per block across all pages.","operationId":"protected_save_teams_in_pages_api_websites__website_id__pages_save_teams_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/blocks-summary":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Pages Blocks Summary","description":"Blocks of every page.\n\ndepth=top  → top-level blocks + what applying block_type would do (apply-block preview)\ndepth=tree → every block of block_type anywhere in the page (copy-formatting picker)","operationId":"protected_get_pages_blocks_summary_api_websites__website_id__pages_blocks_summary_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"block_type","in":"query","required":false,"schema":{"type":"string","title":"Block Type"}},{"name":"depth","in":"query","required":false,"schema":{"type":"string","default":"top","title":"Depth"}},{"name":"include_props","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Props"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/{page_id}":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Page","operationId":"protected_get_page_api_websites__website_id__pages__page_id__get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Websites - Protected"],"summary":"Protected Update Page","description":"Save page metadata (title / slug / status / SEO custom_meta).\nIf the page is published, the service re-uploads the S3 JSON and\ninvalidates CloudFront so the change is live without needing\nunpublish + republish.","operationId":"protected_update_page_api_websites__website_id__pages__page_id__put","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Websites - Protected"],"summary":"Protected Delete Page","operationId":"protected_delete_page_api_websites__website_id__pages__page_id__delete","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/{page_id}/content":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Page Content","operationId":"protected_get_page_content_api_websites__website_id__pages__page_id__content_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Websites - Protected"],"summary":"Protected Save Page Content","operationId":"protected_save_page_content_api_websites__website_id__pages__page_id__content_put","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/{page_id}/publish":{"post":{"tags":["Websites - Protected"],"summary":"Protected Publish Page","operationId":"protected_publish_page_api_websites__website_id__pages__page_id__publish_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/{page_id}/unpublish":{"post":{"tags":["Websites - Protected"],"summary":"Protected Unpublish Page","operationId":"protected_unpublish_page_api_websites__website_id__pages__page_id__unpublish_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/save-all":{"post":{"tags":["Websites - Protected"],"summary":"Protected Save All Pages","description":"Save blocks for multiple pages at once.\n\nRequest body:\n{\n    \"pages\": [\n        {\"page_id\": 1, \"blocks\": [...]},\n        {\"page_id\": 2, \"blocks\": [...]},\n        ...\n    ]\n}\n\nReturns:\n{\n    \"success\": true,\n    \"saved_count\": 5,\n    \"saved_pages\": [1, 2, 3, 4, 5],\n    \"errors\": null\n}","operationId":"protected_save_all_pages_api_websites__website_id__pages_save_all_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/{page_id}/content-type":{"put":{"tags":["Websites - Protected"],"summary":"Protected Change Page Content Type","description":"Change the content type of a page.\n\nCannot change content type if:\n- Page is a system page (is_system = true)\n- New content_type_id doesn't belong to this website\n\nRequest body:\n{\n    \"content_type_id\": 24\n}\n\nReturns:\n{\n    \"success\": true,\n    \"page_id\": 123,\n    \"old_content_type_id\": 30,\n    \"new_content_type_id\": 24\n}","operationId":"protected_change_page_content_type_api_websites__website_id__pages__page_id__content_type_put","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/apply-block":{"put":{"tags":["Websites - Protected"],"summary":"Protected Apply Block","description":"Apply a block to multiple pages at once.\n\n- Replaces existing block of same type, or inserts at start (header) / end (footer)\n- Generates new unique IDs for each page to prevent collisions\n\nRequest body:\n{\n    \"block\": { \"id\": \"...\", \"type\": \"BarraSuperior\", \"props\": {...}, \"children\": [...] },\n    \"page_ids\": [1, 2, 3, 5]\n}","operationId":"protected_apply_block_api_websites__website_id__apply_block_put","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/apply-format":{"put":{"tags":["Websites - Protected"],"summary":"Protected Apply Format","description":"Copy one block's FORMATTING onto blocks of the same type on other pages.\n\nThe client says WHICH prop keys count as formatting (it holds the ui-kit\nschema); the values are always read from the source block already stored for\nthis company, so this endpoint can never write content the tenant did not\nalready have. Content on the target blocks (texts, images, slides) is left\nalone — styled text fields keep their own .text.\n\nRequest body:\n{\n    \"source_page_id\": 12,\n    \"source_block_id\": \"block-...\",\n    \"prop_keys\": [\"height\", \"overlay\"],\n    \"styled_text_keys\": [\"title\", \"subtitle\"],\n    \"targets\": [{\"page_id\": 14, \"block_ids\": [\"block-...\"]}]\n}","operationId":"protected_apply_format_api_websites__website_id__apply_format_put","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/company-data":{"get":{"tags":["Websites - Protected"],"summary":"Get Company Data","description":"Get all company data for block prefilling.\nReturns company info, brand, PontosDeVenda, teams with members.","operationId":"get_company_data_api_websites__website_id__company_data_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/extract-business-info":{"post":{"tags":["Websites - Protected"],"summary":"Extract Business Info","description":"Extract business info from an existing website URL or manual input.\nReuses the AI extraction pipeline from ai_website_generator.","operationId":"extract_business_info_api_websites__website_id__extract_business_info_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/rewrite-page-content":{"post":{"tags":["Websites - Protected"],"summary":"Rewrite Page Content","description":"AI-rewrite text content in a page's blocks while preserving structure.\nUsed to replace generic template text with company-specific content.","operationId":"rewrite_page_content_api_websites__website_id__rewrite_page_content_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/copy-template":{"post":{"tags":["Websites - Protected"],"summary":"Copy Template","description":"Copy a template website's pages, content types, and S3 assets\ninto the target website. Theme is NOT copied (managed separately).\n\nBody: {\"source_website_id\": int}","operationId":"copy_template_api_websites__website_id__copy_template_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/adapt-template":{"post":{"tags":["Websites - Protected"],"summary":"Adapt Template","description":"Use AI to adapt template content to match dealer info (async with image generation).\nReturns a job_id — poll GET /websites/{website_id}/generate/{job_id} for progress.","operationId":"adapt_template_api_websites__website_id__adapt_template_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/adapt-copy":{"post":{"tags":["Websites - Protected"],"summary":"Adapt Copy","description":"Start an AI rewrite of every text on the site (text only — no images).\n\nBody is the same flat dealer-info shape the template wizard already builds,\nplus an optional free-text `instructions`.","operationId":"adapt_copy_api_websites__website_id__adapt_copy_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/adapt-copy/estimate":{"get":{"tags":["Websites - Protected"],"summary":"Adapt Copy Estimate","description":"How many texts each intensity level would send to the AI.\n\nDeterministic and cheap: it runs the same collector + tier classifier the\njob uses, with NO AI call and no CDN fetch. Returns all three counts in one\nresponse so switching level in the UI needs no extra request.","operationId":"adapt_copy_estimate_api_websites__website_id__adapt_copy_estimate_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/adapt-copy/history":{"get":{"tags":["Websites - Protected"],"summary":"Adapt Copy History","description":"Past copy adaptations for this site, newest first.\n\nRead from the jobs table, never from an S3 listing: staging-domain prefixes\ncollapse `x.pt` and `x.com` onto one folder, so a prefix is not a tenant\nboundary.","operationId":"adapt_copy_history_api_websites__website_id__adapt_copy_history_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/adapt-copy/undo":{"post":{"tags":["Websites - Protected"],"summary":"Adapt Copy Undo","description":"Revert the texts changed by a previous adaptation, leaf by leaf.\n\nTakes a `job_id`, never a storage key: the tenant boundary is the\njob→website→company chain, not a client-supplied path.","operationId":"adapt_copy_undo_api_websites__website_id__adapt_copy_undo_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/setup-domain":{"post":{"tags":["Websites - Protected"],"summary":"Protected Setup Domain","description":"Kick off full domain setup (SSL via acme.sh + Nginx + CloudFront) in the\nbackground and return immediately.\n\nThe acme.sh DNS-01 issue waits ~60s for DNS propagation — longer than the\nbrowser will hold the request — so this returns {status: 'running'} right\naway and the BO polls GET /setup-status until 'done' or 'error'. The work\nitself is the same idempotent, self-healing state machine (see\n_do_domain_setup).","operationId":"protected_setup_domain_api_websites__website_id__setup_domain_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/setup-status":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Setup Status","description":"Poll the status of a background setup-domain run (see protected_setup_domain).","operationId":"protected_get_setup_status_api_websites__website_id__setup_status_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/dns-config":{"get":{"tags":["Websites - Protected"],"summary":"Protected Get Dns Config","description":"Return the expected DNS records the customer must set for this website,\nplus current CloudFront distribution + ACM cert status. Drives the\nBO 'Configuração DNS' screen so the expected CNAME target is the per-\nwebsite CloudFront domain (not the legacy `websites.multigest.pt`).","operationId":"protected_get_dns_config_api_websites__website_id__dns_config_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/ssl-status":{"get":{"tags":["Websites - Protected"],"summary":"Protected Check Ssl Status","description":"Verify the *real* HTTPS state of the website's public `www` domain.\n\nChecks that www.<domain> is registered as an Alternate Domain Name on the\nsite's CloudFront distribution AND that the distribution's attached ACM\ncert is ISSUED and covers it. This is the authoritative \"is SSL working\"\nanswer — it does NOT check the EC2 apex Let's Encrypt cert, which says\nnothing about the CloudFront www path and previously caused a false\n\"Certificado SSL encontrado\" while the site was actually down.","operationId":"protected_check_ssl_status_api_websites__website_id__ssl_status_get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/obtain-ssl":{"post":{"tags":["Websites - Protected"],"summary":"Protected Obtain Ssl","description":"Obtain SSL certificate only (without deploying Nginx config).\nUseful if you want to get the cert first and deploy config manually.","operationId":"protected_obtain_ssl_api_websites__website_id__obtain_ssl_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/deploy-nginx":{"post":{"tags":["Websites - Protected"],"summary":"Protected Deploy Nginx","description":"Deploy Nginx config only (assumes SSL certificate already exists).","operationId":"protected_deploy_nginx_api_websites__website_id__deploy_nginx_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/nginx-config":{"delete":{"tags":["Websites - Protected"],"summary":"Protected Remove Nginx Config","description":"Remove Nginx config for website's domain.","operationId":"protected_remove_nginx_config_api_websites__website_id__nginx_config_delete","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/nginx/configs":{"get":{"tags":["Websites - Protected"],"summary":"Protected List Nginx Configs","description":"List all Nginx configs on the server.\nAdmin endpoint - lists all configs regardless of company. Requires system_admin\n(ticket #445): this returns every tenant's domains/SSL state server-wide, so it must\nnot be reachable by a merely-authenticated user. Sibling deploy/remove endpoints stay\ntenant-scoped via get_website_by_id_and_company and need no extra gate.","operationId":"protected_list_nginx_configs_api_nginx_configs_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tracking/visitors":{"get":{"tags":["Tracking - Admin"],"summary":"Get website visitors","description":"Get all visitors for a website (admin only)","operationId":"get_visitors_api_tracking_visitors_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-website-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Website-Token"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tracking/visitors/{visitor_id}/events":{"get":{"tags":["Tracking - Admin"],"summary":"Get visitor events","description":"Get all events for a specific visitor (admin only)","operationId":"get_events_api_tracking_visitors__visitor_id__events_get","parameters":[{"name":"visitor_id","in":"path","required":true,"schema":{"type":"string","title":"Visitor Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tracking/marketing-history/{visitor_id}":{"get":{"tags":["Tracking - Admin"],"summary":"Get visitor marketing history/journey","description":"Get complete marketing history for a visitor (visitor journey timeline).\n\nReturns:\n- All visitor events (page views, interactions, form submissions)\n- Visitor identity info (if identified)\n- UTM parameters (traffic source)\n- Device and browser info\n- Lead information (if converted)\n\nUse this to understand the full customer journey from first visit to conversion.","operationId":"get_visitor_marketing_history_api_tracking_marketing_history__visitor_id__get","parameters":[{"name":"visitor_id","in":"path","required":true,"schema":{"type":"string","title":"Visitor Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/generate":{"post":{"tags":["AI Page Generator - Protected"],"summary":"Generate New Page","description":"Start AI page generation job (async with progress tracking).\n\nThis endpoint creates a background job that will:\n1. Fetch the existing website theme and blocks\n2. Use AI to generate a complete page based on user instructions\n3. Maintain consistency with the website's existing theme and design\n4. Follow all UI/UX rules and constraints\n5. Save the page to database and upload to S3\n\nReturns a job_id that can be used to check generation status via:\nGET /api/websites/{website_id}/pages/generate/{job_id}\n\nExample instructions:\n- \"Create a services page showcasing our auto repair services\"\n- \"Generate a financing page explaining our payment options\"\n- \"Create a team page with profiles of our mechanics\"","operationId":"generate_new_page_api_websites__website_id__pages_generate_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratePageRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratePageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/generate/{job_id}":{"get":{"tags":["AI Page Generator - Protected"],"summary":"Get Page Generation Status","description":"Check the status of a page generation job.\n\nReturns detailed information about the job including:\n- Current status (pending, analyzing, generating_page, saving_page, uploading, completed, failed)\n- Progress percentage (0-100)\n- Current step description\n- Error message (if failed)","operationId":"get_page_generation_status_api_websites__website_id__pages_generate__job_id__get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__routes__ai_page_generator__JobStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/{page_id}/modify":{"post":{"tags":["AI Page Generator - Protected"],"summary":"Modify Existing Page","description":"Modify an existing page using AI based on user instructions.\n\nThis endpoint allows conversational AI modifications:\n1. Fetches the existing page blocks\n2. Uses AI to modify the page based on user instructions\n3. Maintains consistency with the website theme\n4. Updates the page in database and re-uploads to S3\n\nYou can call this endpoint multiple times for iterative refinement.\n\nExample instructions:\n- \"Add a testimonials section after the services section\"\n- \"Change the hero banner background to gradient style\"\n- \"Remove the pricing section and add a contact form instead\"\n- \"Make the text more professional and formal\"","operationId":"modify_existing_page_api_websites__website_id__pages__page_id__modify_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifyPageRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifyPageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/generate":{"post":{"tags":["AI Website Generator - Protected"],"summary":"Generate Website","description":"Start AI website generation job.\n\nThis endpoint creates a background job that will:\n1. Scrape the target domain to extract business information\n2. Generate a theme.json based on the website\n3. Generate pages using AI and available blocks\n4. Save everything to the database\n\nReturns a job_id that can be used to check generation status.","operationId":"generate_website_api_websites__website_id__generate_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateWebsiteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateWebsiteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/generate-manual":{"post":{"tags":["AI Website Generator - Protected"],"summary":"Generate Website Manual","description":"Start AI website generation with MANUAL input (no website scraping).\n\nInstead of scraping a URL, provide the company information directly:\n- Company name, description, slogan\n- Contact info (phone, email, address)\n- Services offered\n- Brand colors (hex codes)\n- Tone/style preferences\n\nThe AI will generate:\n1. A complete theme.json with your colors and branding\n2. All website pages (home, about, services, contacts, etc.)\n3. Content tailored to your services and target audience\n\nReturns a job_id that can be used to check generation status.","operationId":"generate_website_manual_api_websites__website_id__generate_manual_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManualGenerateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateWebsiteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/generate/{job_id}":{"get":{"tags":["AI Website Generator - Protected"],"summary":"Get Generation Status","description":"Check the status of a website generation job.\n\nReturns detailed information about the job including:\n- Current status (pending, analyzing, generating_theme, generating_pages, completed, failed)\n- Progress percentage (0-100)\n- Current step description\n- Final result (when completed)\n- Error message (if failed)","operationId":"get_generation_status_api_websites__website_id__generate__job_id__get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__routes__ai_generator__JobStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/generate/{job_id}/resume":{"post":{"tags":["AI Website Generator - Protected"],"summary":"Resume Generation","description":"Resume a paused website generation job with user's edits.\n\nCalled when the frontend shows a review form (core values or page selection)\nand the user confirms their changes.","operationId":"resume_generation_api_websites__website_id__generate__job_id__resume_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResumeGenerationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/generate/{job_id}/cancel":{"post":{"tags":["AI Website Generator - Protected"],"summary":"Cancel Generation","description":"Cancel a website generation job (works at any stage, especially during wizard pauses).","operationId":"cancel_generation_api_websites__website_id__generate__job_id__cancel_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/generate-ad-description":{"post":{"tags":["AI Website Generator - Protected"],"summary":"Generate Ad Description Endpoint","description":"Generate AI-powered vehicle ad description using Claude Haiku (cheapest model).\n\nOption 1: Provide listing_id to fetch vehicle data from ViaturasEasyDataGreen\nOption 2: Provide vehicle data directly (marca, modelo, ano, kms, combustivel, etc.)\n\nParameters:\n    - listing_id: ID from ViaturasEasyDataGreen (optional)\n    - marca, modelo, ano, kms, combustivel: Direct vehicle data (optional)\n    - potencia, cor, mes: Additional vehicle data (optional)\n    - max_words: Maximum word count (default 50)\n    - tone: Desired tone (default \"profissional mas apelativo\")\n    - language: Output language (default \"Portugues de Portugal\")","operationId":"generate_ad_description_endpoint_api_generate_ad_description_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdDescriptionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdDescriptionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/generate-images":{"post":{"tags":["AI Image Generator - Protected"],"summary":"Generate Images For Website","description":"Generate AI images for ALL pages (background job).","operationId":"generate_images_for_website_api_websites__website_id__generate_images_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/generate-single-image":{"post":{"tags":["AI Image Generator - Protected"],"summary":"Generate Single Image","description":"Start an AI image generation job. Returns {job_id} immediately; client polls\nGET /websites/{website_id}/generate-image/{job_id} for the result.\n\nBody: {\"prompt\": \"...\", \"use_context\": true, \"page_slug\": \"...\",\n       \"block_type\": \"...\", \"block_props\": {...},\n       \"aspect_ratio\": \"16:9\",   # optional — one of 1:1,2:3,3:2,3:4,4:3,9:16,16:9,21:9\n       \"image_size\": \"2K\"}       # optional — 1K | 2K | 4K (default 2K)","operationId":"generate_single_image_api_websites__website_id__generate_single_image_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/generate-image/{job_id}":{"get":{"tags":["AI Image Generator - Protected"],"summary":"Get Image Generation Status","description":"Poll status of a single-image generation job started by\nPOST /websites/{website_id}/generate-single-image or\nPOST /websites/{website_id}/pages/{page_id}/blocks/{block_id}/regenerate-image.\n\nReturns the same shape as `get_generation_job` — when status == \"completed\",\n`result.url` is the CDN URL.","operationId":"get_image_generation_status_api_websites__website_id__generate_image__job_id__get","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/websites/{website_id}/pages/{page_id}/blocks/{block_id}/regenerate-image":{"post":{"tags":["AI Image Generator - Protected"],"summary":"Regenerate Block Image Route","description":"Start a job to regenerate the AI image of a single block. Returns\n{job_id} immediately; client polls GET /websites/{website_id}/generate-image/{job_id}.\nOn completion, `result.block` contains the updated block JSON.","operationId":"regenerate_block_image_route_api_websites__website_id__pages__page_id__blocks__block_id__regenerate_image_post","parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"integer","title":"Website Id"}},{"name":"page_id","in":"path","required":true,"schema":{"type":"integer","title":"Page Id"}},{"name":"block_id","in":"path","required":true,"schema":{"type":"string","title":"Block Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles-with-context":{"get":{"tags":["Vehicles Lead Context - Protected"],"summary":"Get vehicles with lead context","description":"Get vehicles with comprehensive lead context.\n\nThis endpoint provides full vehicle information with lead context for AI agent queries.\nSupports flexible filtering on multiple parameters.\n\nReturns comprehensive vehicle data including:\n- Basic details (brand, model, version, year, kms, price)\n- Point of sale information\n- Technical specifications\n- Registration details\n- Stock management info\n- Status flags\n- Media (pictures)\n\n**Authentication required**: Company ID extracted from authenticated user.","operationId":"api_get_vehicles_with_context_api_vehicles_with_context_get","parameters":[{"name":"pv_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by point of sale ID","title":"Pv Id"},"description":"Filter by point of sale ID"},{"name":"brand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by brand (partial match)","title":"Brand"},"description":"Filter by brand (partial match)"},{"name":"model","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by model (partial match)","title":"Model"},"description":"Filter by model (partial match)"},{"name":"fuel_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by fuel type (e.g., Gasolina, Diesel, Elétrico)","title":"Fuel Type"},"description":"Filter by fuel type (e.g., Gasolina, Diesel, Elétrico)"},{"name":"gearbox","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by gearbox (e.g., Manual, Automática)","title":"Gearbox"},"description":"Filter by gearbox (e.g., Manual, Automática)"},{"name":"year_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":2100,"minimum":1900},{"type":"null"}],"description":"Minimum year","title":"Year Min"},"description":"Minimum year"},{"name":"year_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":2100,"minimum":1900},{"type":"null"}],"description":"Maximum year","title":"Year Max"},"description":"Maximum year"},{"name":"price_min","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Minimum price","title":"Price Min"},"description":"Minimum price"},{"name":"price_max","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Maximum price","title":"Price Max"},"description":"Maximum price"},{"name":"kms_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Maximum kilometers","title":"Kms Max"},"description":"Maximum kilometers"},{"name":"is_imported","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter imported vehicles","title":"Is Imported"},"description":"Filter imported vehicles"},{"name":"condition","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by condition (e.g., Usado, Novo)","title":"Condition"},"description":"Filter by condition (e.g., Usado, Novo)"},{"name":"body_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by body type","title":"Body Type"},"description":"Filter by body type"},{"name":"segment_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by segment name","title":"Segment Name"},"description":"Filter by segment name"},{"name":"color","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by vehicle color","title":"Color"},"description":"Filter by vehicle color"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/me/companies":{"get":{"tags":["Company Access"],"summary":"List companies the current user can access","description":"Returns the user's home company plus any shared-access companies.\nUsed by the frontend company switcher dropdown.","operationId":"list_my_companies_api_users_me_companies_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List My Companies Api Users Me Companies Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company-access":{"get":{"tags":["Company Access"],"summary":"List shared users for your company","description":"Lists all external users who have shared access to the current company.\nUsed by company admins to manage shared access.","operationId":"list_shared_users_api_company_access_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Shared Users Api Company Access Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company-access/{access_id}":{"delete":{"tags":["Company Access"],"summary":"Revoke shared access","description":"Revokes a user's shared access to the current company (soft-delete).","operationId":"revoke_shared_access_api_company_access__access_id__delete","parameters":[{"name":"access_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Access Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Shared Access Api Company Access  Access Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/me":{"get":{"tags":["Users - Admin"],"summary":"Get current authenticated user","description":"Returns the current authenticated user's information from the JWT token.","operationId":"get_current_user_info_api_users_me_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users":{"get":{"tags":["Users - Admin"],"summary":"List users for the current company","description":"Lists users belonging to the authenticated user's company.\n\nBy default only active users are returned. ``include_inactive=true`` also\nreturns excluded (soft-deleted, ativo=0) users, but ONLY for a company admin\n— for anyone else (including system_admin/platform staff) the flag is coerced\nto False so excluded colleagues are never exposed. Uses the same auth context\nas /leads routes.","operationId":"api_list_users_api_users_get","parameters":[{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Optional team ID filter","title":"Team Id"},"description":"Optional team ID filter"},{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","description":"Company-admin only: also include excluded (ativo=0) users. Silently ignored for non-admins.","default":false,"title":"Include Inactive"},"description":"Company-admin only: also include excluded (ativo=0) users. Silently ignored for non-admins."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/{user_id}":{"get":{"tags":["Users - Admin"],"summary":"Get a single user by ID","description":"Returns detailed information about a specific user.\nOnly returns users from the authenticated user's company.","operationId":"get_user_details_api_users__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get User Details Api Users  User Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Users - Admin"],"summary":"Update a user","description":"Updates a user's information.\n\nAllowed fields:\n- Nome: User's full name\n- email: User's email address\n- contact_number: Phone number\n- username: Login username\n- superior: ID of the user's manager\n- pontodevenda: Point of sale ID (reassign POS)\n- website_photo_url: Profile photo URL\n- website_role: Role displayed on website\n- website_description: Bio/description for website\n- website_visible: Whether visible on website (bit)\n\nPayroll fields (written to the linked Cliente row, not Utilizadores; a\nclient is created + linked lazily if the user doesn't have one yet):\n- nif: Tax ID (int; blank clears it)\n- iban: Salary IBAN (\"IBAN Vencimento\")\n- iban_alimentar: Food-allowance IBAN (\"IBAN Alimentação\")","operationId":"update_user_api_users__user_id__put","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update User Api Users  User Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Users - Admin"],"summary":"Deactivate a user","description":"Deactivates a user (soft delete).\nThe user will no longer appear in listings but their data is preserved.\n\nRefuses with 409 when the deactivation would leave the company with no\nACTIVE user able to reach access management (`SELF_LOCKOUT_MODULES`) — see\n`user_roles_db.deactivate_user_with_lockout_guard`, which owns that\ninvariant inside the write transaction.","operationId":"deactivate_user_api_users__user_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/{user_id}/photo":{"post":{"tags":["Users - Admin"],"summary":"Upload a user's profile photo","description":"Uploads a profile photo for a user. The image is re-encoded to WebP\nserver-side and stored in the public websites bucket under\n{staging_domain}/assets/users/photos/ so it's servable via CloudFront\nfor the company's public website. Requires the company to have at\nleast one Website record — otherwise upload is refused.\nUpdates Utilizadores.website_photo_url with the resulting CDN URL.","operationId":"upload_user_photo_api_users__user_id__photo_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_user_photo_api_users__user_id__photo_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upload User Photo Api Users  User Id  Photo Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/{user_id}/reactivate":{"post":{"tags":["Users - Admin"],"summary":"Reactivate a deactivated user","description":"Reactivates a previously deactivated user.","operationId":"reactivate_user_api_users__user_id__reactivate_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reactivate User Api Users  User Id  Reactivate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/points-of-sale":{"get":{"tags":["Company - Admin"],"summary":"List all points of sale for the current company","description":"Returns all Pontos de Venda (Points of Sale) for the authenticated user's company.","operationId":"list_points_of_sale_api_points_of_sale_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Points Of Sale Api Points Of Sale Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Company - Admin"],"summary":"Create a new point of sale for the current company","description":"Create a new Ponto de Venda (Point of Sale) for the authenticated user's company.\nAccepts frontend field names and maps them to DB columns.\nCopies NIPC from the first PV if not provided, and assigns the company's current plan.","operationId":"api_create_point_of_sale_api_points_of_sale_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Create Point Of Sale Api Points Of Sale Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/points-of-sale/{pv_id}":{"put":{"tags":["Company - Admin"],"summary":"Update a point of sale","description":"Update a Ponto de Venda (Point of Sale) by ID.\nOnly updates PVs belonging to the authenticated user's company.","operationId":"api_update_point_of_sale_api_points_of_sale__pv_id__put","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Update Point Of Sale Api Points Of Sale  Pv Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company":{"get":{"tags":["Company - Admin"],"summary":"Get current company info","description":"Returns the current user's company (Empresa) info.","operationId":"get_company_api_company_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Company Api Company Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Company - Admin"],"summary":"Update current company info","description":"Update the current user's company (Empresa) info.","operationId":"api_update_company_api_company_put","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Update Company Api Company Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invitations":{"post":{"tags":["Invitations - Admin"],"summary":"Create a new invitation","description":"Creates a new invitation and sends an email to the invitee.\n\nRequired fields:\n- email: The email address to invite\n- idpointofsale: The point of sale to assign\n- idrole: the role to grant (see `_validated_idrole` — REQUIRED since\n  2026-07-30; omitting it used to mean \"all 22 modules\")\n\nOptional fields:\n- fullname: The invitee's name","operationId":"create_new_invitation_api_invitations_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create New Invitation Api Invitations Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Invitations - Admin"],"summary":"List all invitations for the company","description":"Lists all invitations for the authenticated user's company.\nOptionally filter by status (pending, accepted, revoked, expired).","operationId":"list_company_invitations_api_invitations_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Company Invitations Api Invitations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invitations/reinvite/{utilizador_id}":{"post":{"tags":["Invitations - Admin"],"summary":"Reinvite an excluded user whose Cognito login was purged","description":"Re-onboards an excluded (ativo=0) user whose Cognito account was hard-deleted by\nthe dormant-cleanup cron. Creates a fresh Cognito user (sending the setup email),\nrewrites the Z_Users + Utilizadores cognito_sub, and reactivates the existing row\n— optionally at a new point of sale / role (a rehire may land at a different loja).\n\nThe existing row is REUSED (never re-inserted) because cognito_sub /\nZ_Users.email / Z_Users.cognitosub are all UNIQUE. Reactivating + relinking\nBEFORE first login means auth joins cleanly on the new sub and the fragile\nauto-create/claim path is never taken.\n\nRestricted to the company's OWN admin (not system_admin) — same gate as reactivation.","operationId":"reinvite_excluded_user_api_invitations_reinvite__utilizador_id__post","parameters":[{"name":"utilizador_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Utilizador Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reinvite Excluded User Api Invitations Reinvite  Utilizador Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invitations/{invitation_id}":{"delete":{"tags":["Invitations - Admin"],"summary":"Revoke an invitation","description":"Revokes a pending invitation.\nAlso cleans up Cognito user and Z_Users record.\nOnly works if the invitation is still pending.","operationId":"revoke_company_invitation_api_invitations__invitation_id__delete","parameters":[{"name":"invitation_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Invitation Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invitations/{invitation_id}/resend":{"post":{"tags":["Invitations - Admin"],"summary":"Resend an invitation email","description":"Resends an invitation. Only works for pending invitations belonging to the\nuser's company.\n\nTwo shapes, decided by the Cognito account status:\n\n* `FORCE_CHANGE_PASSWORD` — an ordinary invitee who never signed in. Cognito\n  re-sends the temporary password, as before.\n* `CONFIRMED` — someone who already has a StandGest login (a self-signup\n  account invited to join the company). `admin_resend_invitation` raises\n  `UnsupportedUserStateException` for these, which used to make \"Reenviar\" a\n  button that could never work; they get the branded tokenized link instead.\n\n**The expiry is pushed out too.** Nothing in this codebase ever writes\n`status='expired'` — the row just sits `'pending'` with a past `expires_at` —\nso re-sending a lapsed invitation used to hand out a working password and a\ntoken `claim_invitation` still refuses, with no way out of the loop.","operationId":"resend_invitation_api_invitations__invitation_id__resend_post","parameters":[{"name":"invitation_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Invitation Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Resend Invitation Api Invitations  Invitation Id  Resend Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invitations/bulk":{"post":{"tags":["Invitations - Admin"],"summary":"Bulk create invitations","description":"Create up to 20 invitations at once.\n\nRequired body:\n- invitations: list of {email, fullname (optional), idpointofsale,\n  idrole (optional — see below)}\n\nOptional body:\n- idrole: a default applied to every item that omits its own.\n\n**Every row must end up with a role**, exactly like `POST /invitations`. The\nrole may arrive per item or as the batch-level default, but a row that\nresolves to neither is refused.\n\nThis used to be optional, on the argument that none of the endpoint's callers\noffered a role field so nobody could be deceived about which one took effect,\nand that the first-run onboarding wizard had no roles to choose from anyway.\nBoth halves are gone: the wizard now has a role picker (companies get their\ntemplate copies at creation, so the list is never empty), and the `Completo`\nfallback the argument leaned on has been removed — a roleless invitation\ntoday grants NOTHING, which is a worse silent outcome than the one the\noptionality was defending.\n\nRefusal is PER ROW rather than a 400 for the batch: this endpoint's contract\nis best-effort, and a stale tab posting twenty roleless rows should surface\ntwenty readable errors, not discard nineteen valid invitations.\n\nReturns per-item results with success/error status.\nContinues on individual failures (best-effort).","operationId":"bulk_create_invitations_api_invitations_bulk_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bulk Create Invitations Api Invitations Bulk Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/invitations/claim":{"post":{"tags":["Invitations - Admin"],"summary":"Claim an invitation (authenticated user)","description":"Claims an invitation for the authenticated user.\nThis creates the Utilizadores record and updates Z_Users.\n\nRequired fields:\n- token: The invitation token\n\nThe user must be authenticated via Cognito and their email must match the invitation.","operationId":"claim_user_invitation_api_invitations_claim_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Claim User Invitation Api Invitations Claim Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/multidrive/list":{"post":{"tags":["MultiDrive - Internal Storage"],"summary":"List files and folders in MultiDrive","description":"List files/folders. Path determines what to show:\n- \"\" → PV list\n- \"pv/{id}\" → module folders\n- \"pv/{id}/Ficheiros/...\" → user files\n- \"pv/{id}/{VirtualFolder}/...\" → module files (read-only)\n- \"website/{domain}/...\" → website assets (read-only)","operationId":"list_multidrive_api_multidrive_list_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Multidrive Api Multidrive List Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/multidrive/upload":{"post":{"tags":["MultiDrive - Internal Storage"],"summary":"Upload files to MultiDrive","description":"Upload files to the company's MultiDrive. Only writable in Ficheiros folders.","operationId":"upload_multidrive_api_multidrive_upload_post","parameters":[{"name":"prefix","in":"query","required":false,"schema":{"type":"string","description":"Folder path (must be under pv/{id}/Ficheiros)","default":"","title":"Prefix"},"description":"Folder path (must be under pv/{id}/Ficheiros)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_multidrive_api_multidrive_upload_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Upload Multidrive Api Multidrive Upload Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/multidrive/folder":{"post":{"tags":["MultiDrive - Internal Storage"],"summary":"Create a folder in MultiDrive","description":"Create a folder. Only allowed in Ficheiros.","operationId":"create_folder_api_multidrive_folder_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FolderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Create Folder Api Multidrive Folder Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["MultiDrive - Internal Storage"],"summary":"Delete a folder and all contents from MultiDrive","description":"Delete a folder recursively. Only allowed in Ficheiros.","operationId":"delete_folder_api_multidrive_folder_delete","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Folder Api Multidrive Folder Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/multidrive/file":{"delete":{"tags":["MultiDrive - Internal Storage"],"summary":"Delete a file from MultiDrive","description":"Delete a file. Only allowed in Ficheiros.","operationId":"delete_file_api_multidrive_file_delete","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Delete File Api Multidrive File Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/multidrive/move":{"post":{"tags":["MultiDrive - Internal Storage"],"summary":"Move or rename a file/folder in MultiDrive","description":"Move/rename a file or folder. Only allowed in Ficheiros.","operationId":"move_item_api_multidrive_move_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Move Item Api Multidrive Move Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/multidrive/download":{"post":{"tags":["MultiDrive - Internal Storage"],"summary":"Get a presigned download URL for a file","description":"Generate a presigned URL to download a file.\nWorks for both user files (Ficheiros) and virtual folder files (read-only).","operationId":"get_download_url_api_multidrive_download_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Download Url Api Multidrive Download Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/multidrive/storage-summary":{"get":{"tags":["MultiDrive - Internal Storage"],"summary":"Get storage usage summary","description":"Returns pre-computed storage summary (generated daily by cron job).\nReads {company_id}/storage_summary.json from S3.","operationId":"get_storage_summary_api_multidrive_storage_summary_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Storage Summary Api Multidrive Storage Summary Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/multidrive/public-url":{"post":{"tags":["MultiDrive - Internal Storage"],"summary":"Get the public URL for a file in Ficheiros Publicos","description":"Returns the permanent public URL for a file in 'Ficheiros Publicos'.\nOnly works for files stored in the public multidrive bucket.","operationId":"get_public_url_api_multidrive_public_url_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Public Url Api Multidrive Public Url Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/excel/template":{"get":{"tags":["Vehicle Import"],"summary":"Download Template","description":"Stream the canonical workbook with dropdowns sourced from this company/PV.","operationId":"download_template_api_vehicle_import_excel_template_get","parameters":[{"name":"pv_id","in":"query","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/excel/validate":{"post":{"tags":["Vehicle Import"],"summary":"Validate Workbook","description":"Dry-run: resolve every row and return the report. Writes nothing.","operationId":"validate_workbook_api_vehicle_import_excel_validate_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_validate_workbook_api_vehicle_import_excel_validate_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/excel/import":{"post":{"tags":["Vehicle Import"],"summary":"Import Workbook","description":"Import an uploaded workbook. Returns a job id; poll GET /jobs/{job_id}.","operationId":"import_workbook_api_vehicle_import_excel_import_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_workbook_api_vehicle_import_excel_import_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/excel/jobs/{job_id}":{"get":{"tags":["Vehicle Import"],"summary":"Get Import Job","description":"Poll an import job. 404 when unknown/expired (or Redis unavailable).","operationId":"get_import_job_api_vehicle_import_excel_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/scrape":{"post":{"tags":["Vehicle Import"],"summary":"Start Scrape Job","description":"Start a scrape job asynchronously.\nReturns immediately with the job_id. Poll GET /scrape-jobs/{id} for progress.","operationId":"start_scrape_job_api_vehicle_import_scrape_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/scrape-jobs":{"get":{"tags":["Vehicle Import"],"summary":"List Scrape Jobs","description":"List scrape jobs for the authenticated user's company, newest first.","operationId":"list_scrape_jobs_api_vehicle_import_scrape_jobs_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/scrape-jobs/{job_id}":{"get":{"tags":["Vehicle Import"],"summary":"Get Scrape Job","description":"Get a single scrape job by ID, including progress counters.","operationId":"get_scrape_job_api_vehicle_import_scrape_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Vehicle Import"],"summary":"Delete Scrape Job","description":"Delete a scrape job and all its scraped vehicles.","operationId":"delete_scrape_job_api_vehicle_import_scrape_jobs__job_id__delete","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/scrape-jobs/{job_id}/vehicles":{"get":{"tags":["Vehicle Import"],"summary":"Get Scraped Vehicles","description":"Get all scraped vehicles for a job. Returns raw text + resolved IDs.","operationId":"get_scraped_vehicles_api_vehicle_import_scrape_jobs__job_id__vehicles_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/scraped/{vehicle_id}":{"put":{"tags":["Vehicle Import"],"summary":"Update Scraped Vehicle","description":"Edit a scraped vehicle's fields (fix unresolved IDs, correct data).","operationId":"update_scraped_vehicle_api_vehicle_import_scraped__vehicle_id__put","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-import/import":{"post":{"tags":["Vehicle Import"],"summary":"Import Vehicles","description":"Import selected scraped vehicles into a company's Viatura table.\nOptionally downloads and uploads photos to S3.","operationId":"import_vehicles_api_vehicle_import_import_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/logistica":{"get":{"tags":["Vehicle Logistics"],"summary":"Get Logistica","description":"Get logistics state for a vehicle.","operationId":"get_logistica_api_vehicles__vehicle_id__logistica_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/logistica/localizacao":{"post":{"tags":["Vehicle Logistics"],"summary":"Set Localizacao","description":"Set vehicle location.\nBody: { localizacao: 'parque' | 'transporte' }\nSetting 'parque' directly only allowed if no active transport exists.","operationId":"set_localizacao_api_vehicles__vehicle_id__logistica_localizacao_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/logistica/prep-fim":{"post":{"tags":["Vehicle Logistics"],"summary":"Mark Prep Fim","description":"Mark preparation as complete. Only allowed if prep_fim IS NULL.\nReturns suggest_transporte_saida flag.","operationId":"mark_prep_fim_api_vehicles__vehicle_id__logistica_prep_fim_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/logistica/prep-prevista":{"patch":{"tags":["Vehicle Logistics"],"summary":"Set Prep Prevista","description":"Set or clear the expected preparation completion date (\"data prevista de\nconclusão\"), which the mechanic uses to signal when the vehicle should be\nready. Body: { value: \"2026-08-25\" | null }.\n\nOnly allowed while the preparation is still open — once it is concluded the\ndate is kept as the record of what was predicted, and no longer editable.","operationId":"set_prep_prevista_api_vehicles__vehicle_id__logistica_prep_prevista_patch","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/logistica/pronto-entrega":{"patch":{"tags":["Vehicle Logistics"],"summary":"Toggle Pronto Entrega","description":"Toggle pronto_entrega. Body: { value: bool }","operationId":"toggle_pronto_entrega_api_vehicles__vehicle_id__logistica_pronto_entrega_patch","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/logistica/buffer-block":{"patch":{"tags":["Vehicle Logistics"],"summary":"Toggle Buffer Block","description":"Toggle buffer_block_sale. Body: { value: bool }","operationId":"toggle_buffer_block_api_vehicles__vehicle_id__logistica_buffer_block_patch","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/transportes":{"get":{"tags":["Vehicle Transports"],"summary":"List Vehicle Transportes","description":"List all transports for a vehicle.","operationId":"list_vehicle_transportes_api_vehicles__vehicle_id__transportes_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Vehicle Transports"],"summary":"Create Vehicle Transporte","description":"Create a new transport for a vehicle.\nBody: { tipo, origem, destino, data_recolha?, data_entrega_prevista?, notas? }","operationId":"create_vehicle_transporte_api_vehicles__vehicle_id__transportes_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/transportes":{"get":{"tags":["Vehicle Transports"],"summary":"List Company Transportes","description":"List all transports for the company with optional filters.","operationId":"list_company_transportes_api_transportes_get","parameters":[{"name":"tipo","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tipo"}},{"name":"concluido","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Concluido"}},{"name":"pv_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/transportes/{transport_id}/concluir":{"post":{"tags":["Vehicle Transports"],"summary":"Conclude Transporte","description":"Conclude a transport. Accepts optional multipart photo uploads.\nUploads photos to S3 then marks transport as complete.","operationId":"conclude_transporte_api_transportes__transport_id__concluir_post","parameters":[{"name":"transport_id","in":"path","required":true,"schema":{"type":"integer","title":"Transport Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_conclude_transporte_api_transportes__transport_id__concluir_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/transportes/{transport_id}/cancelar":{"post":{"tags":["Vehicle Transports"],"summary":"Cancel Transporte","description":"Cancel a transport that was created in error. Body: { motivo?: str }.\n\nOnly active transports can be cancelled — concluding one already moved the\nvehicle to its destination park, and undoing that is out of scope. The\nvehicle returns to \"em parque\" so the checkup and location flows unblock.","operationId":"cancel_transporte_api_transportes__transport_id__cancelar_post","parameters":[{"name":"transport_id","in":"path","required":true,"schema":{"type":"integer","title":"Transport Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/transportes/{transport_id}/fotos/{foto_type}":{"get":{"tags":["Vehicle Transports"],"summary":"Get Transport Photo","description":"Get a presigned URL for viewing a transport photo.\nfoto_type: 'cmr' or 'parque'","operationId":"get_transport_photo_api_transportes__transport_id__fotos__foto_type__get","parameters":[{"name":"transport_id","in":"path","required":true,"schema":{"type":"integer","title":"Transport Id"}},{"name":"foto_type","in":"path","required":true,"schema":{"type":"string","title":"Foto Type"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/logistica/kpi":{"get":{"tags":["Vehicle Logistics"],"summary":"Get Kpi","description":"Get logistics KPI counts, scoped by all filters currently applied to\nthe vehicle list. Always Fechado=0 and excludes Suspenso (estado=5).","operationId":"get_kpi_api_logistica_kpi_get","parameters":[{"name":"pv_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Pv Ids"}},{"name":"estado","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by vehicle state ID","title":"Estado"},"description":"Filter by vehicle state ID"},{"name":"current_park_location_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Current Park Location Ids"}},{"name":"consignado","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Consignado"}},{"name":"emprestado","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Emprestado"}},{"name":"seguro","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Seguro"}},{"name":"importado","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Importado"}},{"name":"section_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Section Id"}},{"name":"marca_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Marca Id"}},{"name":"modelo_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Modelo Id"}},{"name":"combustivel_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Combustivel Id"}},{"name":"caixa_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Caixa Id"}},{"name":"fornecedor_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedor Id"}},{"name":"preco_min","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Preco Min"}},{"name":"preco_max","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Preco Max"}},{"name":"ano_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ano Min"}},{"name":"ano_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ano Max"}},{"name":"km_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Km Min"}},{"name":"km_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Km Max"}},{"name":"has_anuncio","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Anuncio"}},{"name":"only_retomas","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Only Retomas"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/park-locations":{"get":{"tags":["Park Locations"],"summary":"List park locations","description":"List active park locations for the authenticated user's company.\n\nPV-owned rows come first (for the \"your own PVs\" picker group), then\nexternal parks alphabetically.","operationId":"list_park_locations_endpoint_api_park_locations_get","parameters":[{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by name/localidade","title":"Q"},"description":"Search by name/localidade"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Park Locations"],"summary":"Create a park location","description":"Create a new external park location.\n\nInline-create path (from Autocomplete) sends just `{name}`. Full path\nfrom the Settings management page sends address + contact fields.","operationId":"create_park_location_endpoint_api_park_locations_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/park-locations/{park_id}":{"get":{"tags":["Park Locations"],"summary":"Get one park location","operationId":"get_park_location_endpoint_api_park_locations__park_id__get","parameters":[{"name":"park_id","in":"path","required":true,"schema":{"type":"integer","title":"Park Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Park Locations"],"summary":"Update a park location","operationId":"update_park_location_endpoint_api_park_locations__park_id__put","parameters":[{"name":"park_id","in":"path","required":true,"schema":{"type":"integer","title":"Park Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Park Locations"],"summary":"Soft-delete a park location","operationId":"delete_park_location_endpoint_api_park_locations__park_id__delete","parameters":[{"name":"park_id","in":"path","required":true,"schema":{"type":"integer","title":"Park Id"}},{"name":"reassign_to","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Optional target park id. When set, all vehicles and transports referencing this park are moved to the target before soft-delete.","title":"Reassign To"},"description":"Optional target park id. When set, all vehicles and transports referencing this park are moved to the target before soft-delete."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/park-locations/{park_id}/reactivate":{"post":{"tags":["Park Locations"],"summary":"Reactivate a soft-deleted park location","operationId":"reactivate_park_location_endpoint_api_park_locations__park_id__reactivate_post","parameters":[{"name":"park_id","in":"path","required":true,"schema":{"type":"integer","title":"Park Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/park-locations/{park_id}/reference-counts":{"get":{"tags":["Park Locations"],"summary":"Count references to a park location","description":"Returns counts of vehicles currently pointing at this park and of\nhistorical transports targeting it — used by the delete confirmation\ndialog to show what will be moved or orphaned.","operationId":"park_location_reference_counts_endpoint_api_park_locations__park_id__reference_counts_get","parameters":[{"name":"park_id","in":"path","required":true,"schema":{"type":"integer","title":"Park Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/park-locations/{park_id}/usage":{"get":{"tags":["Park Locations"],"summary":"Usage report for a park location","description":"Report: distinct vehicles, completed transports, current cars on-site,\nand recent arrivals for a given park over the last `months` months.","operationId":"park_location_usage_endpoint_api_park_locations__park_id__usage_get","parameters":[{"name":"park_id","in":"path","required":true,"schema":{"type":"integer","title":"Park Id"}},{"name":"months","in":"query","required":false,"schema":{"type":"integer","maximum":60,"minimum":1,"description":"Lookback window in months","default":6,"title":"Months"},"description":"Lookback window in months"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/countries":{"get":{"tags":["Countries"],"summary":"List countries","description":"Full list of countries (id, name, isocode), ordered by name.","operationId":"list_countries_endpoint_api_countries_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/combo":{"get":{"tags":["Vehicles (Protected)"],"summary":"Vehicles Combo","description":"Lightweight vehicle list for dropdowns / Autocomplete.\n\nReturns only ID, plates, brand, model, and thumbnail — no heavy JOINs.","operationId":"vehicles_combo_api_vehicles_combo_get","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search plate, brand or model","title":"Search"},"description":"Search plate, brand or model"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/":{"get":{"tags":["Vehicles (Protected)"],"summary":"List Vehicles","description":"List vehicles with pagination and comprehensive filters.\n\nReturns:\n- Matricula (primary or secondary with | separator)\n- Marca, Modelo names\n- Formatted price with VAT indication\n- Calculated profit from movements\n- Days since entry\n- Status flags (consignado, emprestado, seguro, fechado)\n- Alert messages (inspection, ads, etc.)","operationId":"list_vehicles_api_vehicles__get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"description":"Items per page","default":50,"title":"Limit"},"description":"Items per page"},{"name":"ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Re-read exactly these vehicle IDs (bypasses paging, max 100). Used by the stock list to refresh rows edited in another tab.","default":[],"title":"Ids"},"description":"Re-read exactly these vehicle IDs (bypasses paging, max 100). Used by the stock list to refresh rows edited in another tab."},{"name":"pv_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Filter by one or more point of sale IDs","default":[],"title":"Pv Ids"},"description":"Filter by one or more point of sale IDs"},{"name":"fechado","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by closed status (true=closed, false=open)","title":"Fechado"},"description":"Filter by closed status (true=closed, false=open)"},{"name":"estado","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by state ID — dbo.EstadoViatura (1=Por Anunciar, 2=Em Stock, 3=Reservado, 4=Vendido, 5=Suspenso)","title":"Estado"},"description":"Filter by state ID — dbo.EstadoViatura (1=Por Anunciar, 2=Em Stock, 3=Reservado, 4=Vendido, 5=Suspenso)"},{"name":"consignado","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter consigned vehicles","title":"Consignado"},"description":"Filter consigned vehicles"},{"name":"emprestado","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter loaned vehicles","title":"Emprestado"},"description":"Filter loaned vehicles"},{"name":"seguro","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter vehicles with active insurance","title":"Seguro"},"description":"Filter vehicles with active insurance"},{"name":"importado","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter imported vehicles","title":"Importado"},"description":"Filter imported vehicles"},{"name":"section_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by Integrazu section ID","title":"Section Id"},"description":"Filter by Integrazu section ID"},{"name":"marca_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by brand ID","title":"Marca Id"},"description":"Filter by brand ID"},{"name":"modelo_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by model ID","title":"Modelo Id"},"description":"Filter by model ID"},{"name":"combustivel_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by fuel type ID","title":"Combustivel Id"},"description":"Filter by fuel type ID"},{"name":"caixa_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by transmission ID","title":"Caixa Id"},"description":"Filter by transmission ID"},{"name":"second_key_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by second-key status: sim, não, requisitado","title":"Second Key Status"},"description":"Filter by second-key status: sim, não, requisitado"},{"name":"fornecedor_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by supplier (Cliente ID referenced by Viatura.Fornece)","title":"Fornecedor Id"},"description":"Filter by supplier (Cliente ID referenced by Viatura.Fornece)"},{"name":"preco_min","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Minimum price","title":"Preco Min"},"description":"Minimum price"},{"name":"preco_max","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Maximum price","title":"Preco Max"},"description":"Maximum price"},{"name":"ano_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Minimum year (DataMat)","title":"Ano Min"},"description":"Minimum year (DataMat)"},{"name":"ano_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Maximum year (DataMat)","title":"Ano Max"},"description":"Maximum year (DataMat)"},{"name":"km_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Minimum kilometers","title":"Km Min"},"description":"Minimum kilometers"},{"name":"km_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Maximum kilometers","title":"Km Max"},"description":"Maximum kilometers"},{"name":"has_anuncio","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by ad status (true=has ad, false=no ad)","title":"Has Anuncio"},"description":"Filter by ad status (true=has ad, false=no ad)"},{"name":"renew_inactive","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter vehicles with active exports but auto-renew disabled","title":"Renew Inactive"},"description":"Filter vehicles with active exports but auto-renew disabled"},{"name":"only_retomas","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Show only trade-in (retoma) vehicles","title":"Only Retomas"},"description":"Show only trade-in (retoma) vehicles"},{"name":"sem_inspecao","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by inspection validity (true=no valid inspection: overdue or not filled, false=has valid inspection)","title":"Sem Inspecao"},"description":"Filter by inspection validity (true=no valid inspection: overdue or not filled, false=has valid inspection)"},{"name":"iuc_caducado","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by IUC status (true=missed, unsettled IUC deadline; false=IUC in order). 100%-electric vehicles are exempt and never match.","title":"Iuc Caducado"},"description":"Filter by IUC status (true=missed, unsettled IUC deadline; false=IUC in order). 100%-electric vehicles are exempt and never match."},{"name":"localizacao","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by location: 0=parque, 1=transporte","title":"Localizacao"},"description":"Filter by location: 0=parque, 1=transporte"},{"name":"prep_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by prep status: nao_iniciada, em_curso, concluida","title":"Prep Status"},"description":"Filter by prep status: nao_iniciada, em_curso, concluida"},{"name":"pronto_entrega","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by commercial readiness","title":"Pronto Entrega"},"description":"Filter by commercial readiness"},{"name":"buffer_blocked","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by sale block status","title":"Buffer Blocked"},"description":"Filter by sale block status"},{"name":"exclude_buffer_blocked","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Exclude buffer-blocked vehicles","title":"Exclude Buffer Blocked"},"description":"Exclude buffer-blocked vehicles"},{"name":"current_park_location_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Filter by one or more current park location IDs","default":[],"title":"Current Park Location Ids"},"description":"Filter by one or more current park location IDs"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by plate, brand, or model","title":"Search"},"description":"Search by plate, brand, or model"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field: dataentr, preco, km, marca","title":"Sort By"},"description":"Sort field: dataentr, preco, km, marca"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort order: asc or desc","default":"desc","title":"Sort Order"},"description":"Sort order: asc or desc"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Vehicles (Protected)"],"summary":"Create Vehicle","description":"Create new vehicle.\n\nBusiness rules:\n- IDempresa set from user's company\n- Ponto_de_venda set from user's PV if not provided\n- Dataentr defaults to now\n- Quadro must be unique within open vehicles","operationId":"create_vehicle_api_vehicles__post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/filters":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Vehicles Filters","description":"Get all available filter options for the vehicles list.\n\nReturns:\n- pontos_venda: List of points of sale for the company\n- estados: List of vehicle states (Stock, Reservado, Vendido, etc.)\n- marcas: List of all brands\n- combustiveis: List of fuel types\n- caixas: List of gearbox types\n- fornecedores: Clients referenced as supplier by this company's vehicles\n- price_range: Min/max price from company vehicles\n- year_range: Min/max year from company vehicles\n- km_range: Min/max kilometers from company vehicles\n- boolean_filters: List of boolean filter options\n- sort_options: Available sort fields","operationId":"get_vehicles_filters_api_vehicles_filters_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/filters/models/{marca_id}":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Models By Brand","description":"Get models for a specific brand (for cascading dropdown).","operationId":"get_models_by_brand_api_vehicles_filters_models__marca_id__get","parameters":[{"name":"marca_id","in":"path","required":true,"schema":{"type":"integer","title":"Marca Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/check-quadro":{"get":{"tags":["Vehicles (Protected)"],"summary":"Check Quadro","description":"Check if a Quadro (VIN) already exists in open vehicles for this company.\nReturns { available: bool, message: str | null }.","operationId":"check_quadro_api_vehicles_check_quadro_get","parameters":[{"name":"quadro","in":"query","required":true,"schema":{"type":"string","minLength":1,"description":"VIN/Chassis number to check","title":"Quadro"},"description":"VIN/Chassis number to check"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/search":{"get":{"tags":["Vehicles (Protected)"],"summary":"Search Vehicles","description":"Search vehicles by various criteria.\n\nSearches:\n- Matricula (exact, LIKE)\n- MatriculaSecundaria (exact, LIKE)\n- Quadro (exact, LIKE)\n- Marca, Modelo, Cor (SOUNDEX for fuzzy matching)\n\nReturns top 20 results ordered by relevance.","operationId":"search_vehicles_api_vehicles_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"description":"Search term (matricula, quadro, marca, modelo, cor)","title":"Q"},"description":"Search term (matricula, quadro, marca, modelo, cor)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VehicleSearchResponse"},"title":"Response Search Vehicles Api Vehicles Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Vehicle","description":"Get single vehicle by ID.\n\nReturns { vehicle, supplier } — the supplier is included so the frontend\ncan render the current Fornecedor even when it is not in the top-N\nsuppliers dropdown list.\n\nUse separate endpoints for:\n- /data/brands, /data/models - to resolve brand/model names\n- /{vehicle_id}/movements - for financial movements\n- /{vehicle_id}/contracts - for contracts","operationId":"get_vehicle_api_vehicles__vehicle_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Vehicles (Protected)"],"summary":"Update Vehicle","description":"Update existing vehicle.\n\nBusiness rules:\n- Cannot modify if belongs to different company\n- Quadro uniqueness validation if changing\n- Partial updates supported\n- fechado/datafecho are protected — only /fechar can change them (irreversible)\n- When Estado transitions to 5 (Suspenso) and unpublish_ads=true, the vehicle\n  is removed from all websites and Integrazu portals after the state change.","operationId":"update_vehicle_api_vehicles__vehicle_id__put","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"unpublish_ads","in":"query","required":false,"schema":{"type":"boolean","description":"When Estado transitions to 5 (Suspenso), also remove the vehicle from all websites and Integrazu portals.","default":false,"title":"Unpublish Ads"},"description":"When Estado transitions to 5 (Suspenso), also remove the vehicle from all websites and Integrazu portals."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Vehicles (Protected)"],"summary":"Delete Vehicle","description":"Delete vehicle.\n\nBusiness rules:\n- Cannot delete if fechado = True\n- Should check if vehicle has contracts/movements","operationId":"delete_vehicle_api_vehicles__vehicle_id__delete","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/photos/order":{"put":{"tags":["Vehicles (Protected)"],"summary":"Update Photos Order","description":"Update the order of vehicle photos.\n\nArgs:\n    vehicle_id: Vehicle ID\n    photos: List of {url: str, ordem: int} to update order\n\nExample body:\n    [\n        {\"url\": \"https://...\", \"ordem\": 1},\n        {\"url\": \"https://...\", \"ordem\": 2}\n    ]","operationId":"update_photos_order_api_vehicles__vehicle_id__photos_order_put","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Photos"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/ad-status":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Vehicle Ad Status","description":"Return whether a vehicle has any active ads (website listing rows + Integrazu portal exports).\n\nUsed by the frontend to decide whether to prompt the user to remove ads\nwhen transitioning a vehicle to Estado=5 (Suspenso).","operationId":"get_vehicle_ad_status_api_vehicles__vehicle_id__ad_status_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Vehicle Ad Status Api Vehicles  Vehicle Id  Ad Status Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/close-status":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Vehicle Close Status","description":"Get the closed (fechado) status of a vehicle.\nReturns: { fechado: bool }","operationId":"get_vehicle_close_status_api_vehicles__vehicle_id__close_status_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/movimentos/unpaid-check":{"get":{"tags":["Vehicles (Protected)"],"summary":"Check Unpaid Movements","description":"Check if a vehicle has any unpaid movements.\nReturns: { hasUnpaid: bool, total: int, paid: int }","operationId":"check_unpaid_movements_api_vehicles__vehicle_id__movimentos_unpaid_check_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/contratos":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Vehicle Contracts For Close","description":"Fetch contracts linked to a vehicle (for close flow).\nReturns list of { ID, clienteNome, ValorVenda, FaturaID, contratoproposta }","operationId":"get_vehicle_contracts_for_close_api_vehicles__vehicle_id__contratos_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/proposta-paga":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Vehicle Paid Proposal","description":"Find a paid proposal (Estado=9) linked to the vehicle via chassis.\nReturns: { propostaId: int | null }","operationId":"get_vehicle_paid_proposal_api_vehicles__vehicle_id__proposta_paga_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/fechar":{"post":{"tags":["Vehicles (Protected)"],"summary":"Fechar Vehicle","description":"Close vehicle atomically with contract and commission updates.\n\nBody: {\n    contratoId: int,\n    comissoes: [{ userId: int, valorAbsoluto: float, valorPercentual: float }]\n}","operationId":"fechar_vehicle_api_vehicles__vehicle_id__fechar_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/close":{"post":{"tags":["Vehicles (Protected)"],"summary":"Close Vehicle","description":"Close a vehicle.\n\nBusiness rules:\n- Checks for unpaid movements before closing\n- If unpaid movements exist and force=False, returns warning with details\n- If force=True, closes despite unpaid movements\n\nSets:\n- fechado = True\n- datafecho = now\n\nReturns:\n- If unpaid movements exist (and force=False): Warning response with unpaid details\n- If successful: Vehicle data with success message","operationId":"close_vehicle_api_vehicles__vehicle_id__close_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Force close despite unpaid movements","default":false,"title":"Force"},"description":"Force close despite unpaid movements"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/movements":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Vehicle Movements","description":"Get vehicle movements summary.\n\nReturns:\n- Unpaid movements (to pay)\n- Paid movements (before close)\n- Movements after close\n- Totals and counts for each\n\nOptional date_start/date_end filter the period on\nCOALESCE(DataPagamento, DataRegisto) so unpaid rows stay visible.","operationId":"get_vehicle_movements_api_vehicles__vehicle_id__movements_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"date_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Period filter start (YYYY-MM-DD)","title":"Date Start"},"description":"Period filter start (YYYY-MM-DD)"},{"name":"date_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Period filter end, inclusive (YYYY-MM-DD)","title":"Date End"},"description":"Period filter end, inclusive (YYYY-MM-DD)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Vehicle Movements Api Vehicles  Vehicle Id  Movements Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/contracts":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Vehicle Contracts","description":"Get all contracts for a vehicle.\n\nReturns contracts with:\n- Client name\n- Dates (contract, close)\n- Values (reserve, sale)\n- Calculated commission\n\nBy default, suspended contracts (IDestado=3) are hidden. Pass\n`?include_suspended=true` to include them — the frontend toggle drives this.","operationId":"get_vehicle_contracts_api_vehicles__vehicle_id__contracts_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"include_suspended","in":"query","required":false,"schema":{"type":"boolean","description":"Include IDestado=3 (Suspenso) rows","default":false,"title":"Include Suspended"},"description":"Include IDestado=3 (Suspenso) rows"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VehicleContractResponse"},"title":"Response Get Vehicle Contracts Api Vehicles  Vehicle Id  Contracts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/contracts/{contract_id}/retomas":{"get":{"tags":["Vehicles (Protected)"],"summary":"Get Contract Retomas","description":"Get trade-in vehicles (retomas) for a specific contract.\n\nReturns retomas with vehicle details (brand, model, km, etc.)\nwhen linked to an existing vehicle record.","operationId":"get_contract_retomas_api_vehicles__vehicle_id__contracts__contract_id__retomas_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/ficha-parque":{"post":{"tags":["Vehicles (Protected)"],"summary":"Generate Vehicle Ficha Parque","description":"Generate (or regenerate) the Ficha de Parque PDF for a vehicle.\n\nBody: {\"brand_id\": int}\n\nReturns presigned inline + download URLs and the Documentos row id. The row\nis overwritten on regeneration — single Ficha per vehicle lifetime.","operationId":"generate_vehicle_ficha_parque_api_vehicles__vehicle_id__ficha_parque_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/ocr-document":{"post":{"tags":["Vehicles (Protected)"],"summary":"Ler documento de veículo (DUA/livrete) e devolver campos para autofill","description":"OCR a vehicle document (JPEG/PNG/PDF) via Claude Vision and return RAW TEXT\nfields for the create-vehicle form to prefill (id resolution happens in the\nFE, section-scoped — never here).\n\nAccepts ONE OR MORE images so the caller can send the frente AND the verso —\nthe technical fields (cilindrada, potência, combustível, cor, lugares) live on\nthe verso of the DUA/livrete, so a front-only photo can't read them. All\nimages are read together in a single vision call and billed as ONE read.\n\nUnreadable/unsupported input returns success=False (never a 5xx); billing\nonly fires on success. Heavy sync work (CV + PyMuPDF + Anthropic + pyodbc)\nruns in the threadpool so the event loop is never blocked (same pattern as\n/invoices/process-qr).","operationId":"ocr_vehicle_document_api_vehicles_ocr_document_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_ocr_vehicle_document_api_vehicles_ocr_document_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleOcrResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/clear-cache":{"post":{"tags":["Vehicles Data"],"summary":"Clear Cache","description":"Clear all cached vehicles reference data.","operationId":"clear_cache_api_vehicles_data_clear_cache_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/brands":{"get":{"tags":["Vehicles Data"],"summary":"Get Brands","description":"Get all vehicle brands (marcas).","operationId":"get_brands_api_vehicles_data_brands_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BrandComboItem"},"title":"Response Get Brands Api Vehicles Data Brands Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/models/{brand_id}":{"get":{"tags":["Vehicles Data"],"summary":"Get Models","description":"Get models for a specific brand.","operationId":"get_models_api_vehicles_data_models__brand_id__get","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"integer","title":"Brand Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ModelComboItem"},"title":"Response Get Models Api Vehicles Data Models  Brand Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/colors":{"get":{"tags":["Vehicles Data"],"summary":"Get Colors","description":"Get all vehicle colors (cores).\n\ninclude_legacy=true also returns the negative-id rows — an EDIT form needs them to\ndisplay (and re-save) a vehicle that already carries a legacy colour. Filter lists\nomit them. The cache key varies with the flag so the two lists can't poison each\nother.","operationId":"get_colors_api_vehicles_data_colors_get","parameters":[{"name":"include_legacy","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Legacy"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ColorComboItem"},"title":"Response Get Colors Api Vehicles Data Colors Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/fuel-types":{"get":{"tags":["Vehicles Data"],"summary":"Get Fuel Types","description":"Get all fuel types (combustiveis). See get_colors for include_legacy.","operationId":"get_fuel_types_api_vehicles_data_fuel_types_get","parameters":[{"name":"include_legacy","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Legacy"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FuelTypeComboItem"},"title":"Response Get Fuel Types Api Vehicles Data Fuel Types Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/gearbox-types":{"get":{"tags":["Vehicles Data"],"summary":"Get Gearbox Types","description":"Get all gearbox types (caixas).","operationId":"get_gearbox_types_api_vehicles_data_gearbox_types_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GearboxComboItem"},"title":"Response Get Gearbox Types Api Vehicles Data Gearbox Types Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/seats":{"get":{"tags":["Vehicles Data"],"summary":"Get Seats","description":"Get all seat options (lugares).","operationId":"get_seats_api_vehicles_data_seats_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SeatsComboItem"},"title":"Response Get Seats Api Vehicles Data Seats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/doors":{"get":{"tags":["Vehicles Data"],"summary":"Get Doors","description":"Get all door options (portas).","operationId":"get_doors_api_vehicles_data_doors_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DoorsComboItem"},"title":"Response Get Doors Api Vehicles Data Doors Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/categories":{"get":{"tags":["Vehicles Data"],"summary":"Get Categories","description":"Get all vehicle categories/types (tipos).","operationId":"get_categories_api_vehicles_data_categories_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CategoryComboItem"},"title":"Response Get Categories Api Vehicles Data Categories Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/states":{"get":{"tags":["Vehicles Data"],"summary":"Get States","description":"Get all vehicle states (estados).","operationId":"get_states_api_vehicles_data_states_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/StateComboItem"},"title":"Response Get States Api Vehicles Data States Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/points-of-sale":{"get":{"tags":["Vehicles Data"],"summary":"Get Points Of Sale","description":"Get points of sale for the user's company.","operationId":"get_points_of_sale_api_vehicles_data_points_of_sale_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PointOfSaleComboItem"},"title":"Response Get Points Of Sale Api Vehicles Data Points Of Sale Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/suppliers":{"get":{"tags":["Vehicles Data"],"summary":"Get Suppliers","description":"Get suppliers (fornecedores) for the user's company.","operationId":"get_suppliers_api_vehicles_data_suppliers_get","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"include_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Force-include this client ID in the result even if outside TOP N","title":"Include Id"},"description":"Force-include this client ID in the result even if outside TOP N"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SupplierComboItem"},"title":"Response Get Suppliers Api Vehicles Data Suppliers Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/license-plate-codes":{"get":{"tags":["Vehicles Data"],"summary":"Get License Plate Codes","description":"Get EU license plate country codes.","operationId":"get_license_plate_codes_api_vehicles_data_license_plate_codes_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LicensePlateCodeItem"},"title":"Response Get License Plate Codes Api Vehicles Data License Plate Codes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/sections":{"get":{"tags":["Vehicles Data"],"summary":"Get Sections","description":"Get all Integrazu sections (Carros, Comerciais, Motos, etc.).","operationId":"get_sections_api_vehicles_data_sections_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SectionComboItem"},"title":"Response Get Sections Api Vehicles Data Sections Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/versions/{model_id}":{"get":{"tags":["Vehicles Data"],"summary":"Get Versions","description":"Get Integrazu versions for a specific model.","operationId":"get_versions_api_vehicles_data_versions__model_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VersionComboItem"},"title":"Response Get Versions Api Vehicles Data Versions  Model Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/encargos":{"get":{"tags":["Encargos (Liens/Charges)"],"summary":"List vehicle liens","description":"List all encargos (liens/charges) for a vehicle.\n\nMulti-tenancy: Only returns encargos for vehicles belonging to user's company.","operationId":"list_vehicle_encargos_api_vehicles__vehicle_id__encargos_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EncargoResponse"},"title":"Response List Vehicle Encargos Api Vehicles  Vehicle Id  Encargos Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Encargos (Liens/Charges)"],"summary":"Create vehicle lien","description":"Create a new encargo (lien/charge) for a vehicle.\n\nRequired fields:\n- entidade: Entity name (bank, leasing company, etc.)\n- referencia: Reference number/code\n- valor: Amount/value of the lien","operationId":"create_vehicle_encargo_api_vehicles__vehicle_id__encargos_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncargoCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncargoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/encargos/{encargo_id}":{"get":{"tags":["Encargos (Liens/Charges)"],"summary":"Get single lien","description":"Get a single encargo by ID.","operationId":"get_vehicle_encargo_api_vehicles__vehicle_id__encargos__encargo_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"encargo_id","in":"path","required":true,"schema":{"type":"integer","title":"Encargo Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncargoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Encargos (Liens/Charges)"],"summary":"Update lien","description":"Update an existing encargo.\n\nAll fields are optional - only provided fields will be updated.","operationId":"update_vehicle_encargo_api_vehicles__vehicle_id__encargos__encargo_id__put","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"encargo_id","in":"path","required":true,"schema":{"type":"integer","title":"Encargo Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncargoUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncargoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Encargos (Liens/Charges)"],"summary":"Delete lien","description":"Delete an encargo.","operationId":"delete_vehicle_encargo_api_vehicles__vehicle_id__encargos__encargo_id__delete","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"encargo_id","in":"path","required":true,"schema":{"type":"integer","title":"Encargo Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/{vehicle_id}/encargos/request":{"post":{"tags":["Encargos (Liens/Charges)"],"summary":"Request lien certificate","description":"Request a lien certificate from external API.\n\nThis calls the external service (http://13.36.175.211:8097/ask_pedido_certidao)\nto retrieve lien/charge data for a vehicle.\n\nThe response contains the status and any data returned from the external service.","operationId":"request_lien_certificate_api_vehicles__vehicle_id__encargos_request_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LienCertificateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tax-simulator/isv":{"post":{"tags":["Tax Simulator"],"summary":"Calculate ISV","description":"Calculate Imposto Sobre Veiculos (ISV) for a vehicle.\n\nSupports:\n- Passenger vehicles (Tabela A): cilindrada + CO2 components\n- Commercial vehicles (Tabela B): cilindrada only, percentage-based\n- Motorcycles (Tabela C): fixed tax by cilindrada\n- Used EU imports: age discount\n- Hybrid/plug-in/natural gas: special discounts\n\nRequired fields:\n- cilindrada_cm3 (int): Engine displacement in cm3\n- fuel_type (str): gasolina, gasoleo, electrico, hibrido_gasolina,\n                   hibrido_gasoleo, plugin_gasolina, plugin_gasoleo,\n                   gas_natural, gpl\n\nOptional fields:\n- co2_gkm (int): CO2 emissions in g/km\n- emission_test (str): NEDC or WLTP (default: WLTP)\n- vehicle_category (str): passenger, commercial, motorcycle (default: passenger)\n- is_used_import (bool): Is this a used EU import? (default: false)\n- first_registration_date (str): YYYY-MM-DD for age discount\n- electric_range_km (int): Electric range in km (for hybrids)\n- particle_emissions_gkm (float): Particle emissions g/km (diesel)\n- commercial_subtype (str): For Tabela B vehicles\n- is_7_seater_over_2500kg (bool): 7+ seater, >2500kg, not 4x4\n- vehicle_id (int): Pre-fill from existing vehicle in stock\n- tax_year (int): Tax year for rate lookup (default: 2026)","operationId":"calculate_isv_api_tax_simulator_isv_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tax-simulator/vehicle/{vehicle_id}":{"get":{"tags":["Tax Simulator"],"summary":"Get vehicle data for ISV simulation","description":"Fetch vehicle data needed to pre-fill the ISV simulator form.\nReturns cilindrada, CO2, fuel type, registration dates, etc.","operationId":"get_vehicle_for_simulation_api_tax_simulator_vehicle__vehicle_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leadcars/":{"get":{"tags":["Lead Cars (CRM)"],"summary":"List Cars Crm","description":"List this company's vehicles, shaped for the CRM vehicle picker.\n\nReturns:\n- id (**Viatura.ID** — this is the value that goes into Z_Leads.object_id)\n- plate, plate_secondary\n- brand, model, version\n- year, kms, price\n- Estado, EstadoNome\n- pv_id, pv_name\n- main_picture_url\n\nReservado (3) and Vendido (4) vehicles ARE returned — a lead is routinely\nopened against a car that is already reserved or sold. Only Suspenso (5) is\nexcluded. Search needs at least 2 characters; below that the term is ignored.","operationId":"list_cars_crm_api_leadcars__get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by plate, chassis, brand or model (min. 2 chars)","title":"Q"},"description":"Search by plate, chassis, brand or model (min. 2 chars)"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Offset","default":0,"title":"Skip"},"description":"Offset"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Limit","default":50,"title":"Limit"},"description":"Limit"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leadcars/{car_id}":{"get":{"tags":["Lead Cars (CRM)"],"summary":"Get Car Crm","description":"Get a single vehicle by ID.\n\n`car_id` is **Viatura.ID** — the same value stored in Z_Leads.object_id.","operationId":"get_car_crm_api_leadcars__car_id__get","parameters":[{"name":"car_id","in":"path","required":true,"schema":{"type":"integer","title":"Car Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/oficina/prioridades":{"get":{"tags":["Oficina"],"summary":"Get Workshop Priorities","operationId":"get_workshop_priorities_api_oficina_prioridades_get","parameters":[{"name":"idpointofsale","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Idpointofsale"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/oficina/visitas":{"get":{"tags":["Oficina"],"summary":"Get Workshop Visitas","operationId":"get_workshop_visitas_api_oficina_visitas_get","parameters":[{"name":"idpointofsale","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Idpointofsale"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/":{"get":{"tags":["Contracts - Protected"],"summary":"List Contracts","description":"List contracts with pagination and filters.\n\n- **skip**: Pagination offset\n- **limit**: Max results (up to 500)\n- **pv_id**: Filter by point of sale ID\n- **fechado**: Filter by closed status (True/False)","operationId":"list_contracts_api_contracts__get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of records to skip","default":0,"title":"Skip"},"description":"Number of records to skip"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"description":"Max records to return","default":100,"title":"Limit"},"description":"Max records to return"},{"name":"pv_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by point of sale","title":"Pv Id"},"description":"Filter by point of sale"},{"name":"fechado","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by closed status","title":"Fechado"},"description":"Filter by closed status"},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by client name, plate or contract ID","title":"Q"},"description":"Search by client name, plate or contract ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContractListResponse"},"title":"Response List Contracts Api Contracts  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Contracts - Protected"],"summary":"Create Contract","description":"Create new contract.\n\nAutomatically creates commission record for the user.","operationId":"create_contract_api_contracts__post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}":{"get":{"tags":["Contracts - Protected"],"summary":"Get Contract","description":"Get single contract by ID.\n\nReturns contract with basic client/vehicle names.","operationId":"get_contract_api_contracts__contract_id__get","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Contracts - Protected"],"summary":"Update Contract","description":"Update existing contract.\n\nBusiness rules:\n- Cannot modify closed contracts (IDestado = 2) unless explicitly changing state\n- Partial updates supported (only changed fields)","operationId":"update_contract_api_contracts__contract_id__put","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Contracts - Protected"],"summary":"Delete Contract","description":"Hard-delete contract. NOT exposed in the UI — kept for future\nadmin / system tooling. Use POST /{id}/suspend from the application.\n\nBusiness rules:\n- Can delete if IDestado = 1 (open) or 3 (suspended)\n- Cannot delete if IDestado = 2 (closed)","operationId":"delete_contract_api_contracts__contract_id__delete","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/complete":{"get":{"tags":["Contracts - Protected"],"summary":"Get Contract Complete","description":"Get complete contract with all blocks.\n\nReturns:\n- Contract\n- Client block (with addresses)\n- Vehicle block\n- Financial block\n- POS block\n- Retomas (trade-ins)","operationId":"get_contract_complete_api_contracts__contract_id__complete_get","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/suspend-preview":{"get":{"tags":["Contracts - Protected"],"summary":"Get Contract Suspend Preview","description":"Aggregate everything the suspend dialog needs in one call:\ncontract summary, sale-vehicle state + active-transport flag, and the\nlist of retoma vehicles. Tenant-scoped; 404 if not found.","operationId":"get_contract_suspend_preview_api_contracts__contract_id__suspend_preview_get","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/suspend":{"post":{"tags":["Contracts - Protected"],"summary":"Suspend Contract","description":"Suspend a contract (sets `IDestado = 3`) and apply user-chosen side-effects\natomically. See `SuspendContractRequest` for the shape.","operationId":"suspend_contract_api_contracts__contract_id__suspend_post","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuspendContractRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/close":{"post":{"tags":["Contracts - Protected"],"summary":"Close Contract","description":"Close a contract.\n\nSets:\n- Fechado = True\n- IDestado = 2\n- Datafecho = now","operationId":"close_contract_api_contracts__contract_id__close_post","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/reopen":{"post":{"tags":["Contracts - Protected"],"summary":"Reopen Contract","description":"Reopen a closed contract.\n\nSets:\n- Fechado = False\n- IDestado = 1\n- Datafecho = NULL","operationId":"reopen_contract_api_contracts__contract_id__reopen_post","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/client-email":{"get":{"tags":["Contracts - Protected"],"summary":"Get Contract Client Email","description":"Return the contract's client primary email so the frontend can pre-fill\nthe 'Enviar ao cliente' recipient field. Tenant-scoped.","operationId":"get_contract_client_email_api_contracts__contract_id__client_email_get","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/send-to-client":{"post":{"tags":["Contracts - Protected"],"summary":"Send Contract To Client","description":"Send one or more declaration PDFs (Documentos with id_modulo=5) belonging\nto this contract to the client by email. Body:\n    declaration_ids: list[int]  — Documentos.ID rows to attach\n    to_address: str (optional)  — override recipient; otherwise the\n                                   contract's client primary email is used","operationId":"send_contract_to_client_api_contracts__contract_id__send_to_client_post","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/send-invoice-to-client":{"post":{"tags":["Contracts - Protected"],"summary":"Send Contract Invoice To Client","description":"Email the sale invoice (Fatura) linked to this contract to the contract's\nclient. Used by the \"Fechar Viatura\" flow (ticket #548). Body (all optional):\n    to_address: str — override recipient; otherwise the contract's client\n                      primary email is used.","operationId":"send_contract_invoice_to_client_api_contracts__contract_id__send_invoice_to_client_post","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/link-invoice":{"post":{"tags":["Contracts - Protected"],"summary":"Link Invoice","description":"Link an invoice to a contract.\n\nSets Contratos.FaturaID, creates Documentos record (tipodoc=62),\nand closes the contract (IDestado=2).\n\nBody:\n    invoice_id: int — Faturas.ID to link","operationId":"link_invoice_api_contracts__contract_id__link_invoice_post","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/unlink-invoice":{"post":{"tags":["Contracts - Protected"],"summary":"Unlink Invoice","description":"Remove invoice link from a contract.\n\nSets Contratos.FaturaID = NULL.\nBlocked if the vehicle is closed (Viatura.Fechado = True).","operationId":"unlink_invoice_api_contracts__contract_id__unlink_invoice_post","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/combos/guarantees":{"get":{"tags":["Contracts - Protected"],"summary":"Get Guarantees Combo","description":"Get available guarantees for dropdown.\n\nFilters by user's point of sale.","operationId":"get_guarantees_combo_api_contracts_combos_guarantees_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GuaranteeComboItem"},"title":"Response Get Guarantees Combo Api Contracts Combos Guarantees Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/combos/warranties":{"get":{"tags":["Contracts - Protected"],"summary":"Get Warranties Combo","description":"Get available warranties for dropdown from Z_Warranties.\n\nFilters by user's company.","operationId":"get_warranties_combo_api_contracts_combos_warranties_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WarrantyComboItem"},"title":"Response Get Warranties Combo Api Contracts Combos Warranties Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/combos/clients":{"get":{"tags":["Contracts - Protected"],"summary":"Get Clients Combo","description":"Get clients for dropdown.\n\nFilters by user's company.","operationId":"get_clients_combo_api_contracts_combos_clients_get","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientComboItem"},"title":"Response Get Clients Combo Api Contracts Combos Clients Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/combos/salespeople":{"get":{"tags":["Contracts - Protected"],"summary":"Get Salespeople Combo","description":"Get salespeople for the Comercial / Responsável dropdowns.\n\nReturns the company's users who can log in AND hold the Viaturas module —\nnot the legacy `Utilizadores.Comercial` bit, which had drifted far enough\nthat most companies had nobody flagged and the picker was empty. Shared-\naccess colleagues holding a role in THIS company are included, matching the\nmodule gate. See `contracts_service.get_salespeople_list`.","operationId":"get_salespeople_combo_api_contracts_combos_salespeople_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SalespersonComboItem"},"title":"Response Get Salespeople Combo Api Contracts Combos Salespeople Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/client/{client_id}/contracts":{"get":{"tags":["Contracts - Protected"],"summary":"Get Client Contracts","description":"Get all contracts for a specific client.\n\nReturns contracts with vehicle info, ordered by ID descending.\nSuspended contracts (IDestado=3) are hidden by default.","operationId":"get_client_contracts_api_contracts_client__client_id__contracts_get","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"integer","title":"Client Id"}},{"name":"include_suspended","in":"query","required":false,"schema":{"type":"boolean","description":"Include IDestado=3 (Suspenso) rows","default":false,"title":"Include Suspended"},"description":"Include IDestado=3 (Suspenso) rows"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/vehicle/{vehicle_id}/contracts":{"get":{"tags":["Contracts - Protected"],"summary":"Get contracts for a vehicle","description":"List all contracts linked to a vehicle. Suspended hidden by default.","operationId":"get_vehicle_contracts_list_api_contracts_vehicle__vehicle_id__contracts_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"include_suspended","in":"query","required":false,"schema":{"type":"boolean","description":"Include IDestado=3 (Suspenso) rows","default":false,"title":"Include Suspended"},"description":"Include IDestado=3 (Suspenso) rows"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/vehicle/{vehicle_id}/propostas":{"get":{"tags":["Contracts - Protected"],"summary":"Get Vehicle Propostas","description":"Get propostas linked to a vehicle for the financing dropdown.","operationId":"get_vehicle_propostas_api_contracts_vehicle__vehicle_id__propostas_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/vehicle/{vehicle_id}/retoma-value":{"get":{"tags":["Contracts - Protected"],"summary":"Get Vehicle Retoma Value","description":"Get the retoma value for a vehicle from Movimentos (Rubrica=5).","operationId":"get_vehicle_retoma_value_api_contracts_vehicle__vehicle_id__retoma_value_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/vehicle/{vehicle_id}/iva-data":{"get":{"tags":["Contracts - Protected"],"summary":"Get Vehicle Iva Data","description":"Get vehicle RegimeIva and purchase price for IVA calculation.\n\nReturns:\n- RegimeIva: int (regime ID from Viatura table)\n- compraViatura: float (purchase price from Movimentos Rubrica=5)","operationId":"get_vehicle_iva_data_api_contracts_vehicle__vehicle_id__iva_data_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/commissions":{"get":{"tags":["Contracts - Protected"],"summary":"List Contract Commissions","description":"List all commission distributions for a contract.\n\nReturns list of salespeople with their commission values.","operationId":"list_contract_commissions_api_contracts__contract_id__commissions_get","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CommissionDistributionResponse"},"title":"Response List Contract Commissions Api Contracts  Contract Id  Commissions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Contracts - Protected"],"summary":"Create Contract Commission","description":"Add a commission distribution to a contract.\n\nMaximum 6 distributions per contract.","operationId":"create_contract_commission_api_contracts__contract_id__commissions_post","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommissionDistributionCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommissionDistributionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Contracts - Protected"],"summary":"Batch Update Commissions","description":"Batch update all commission distributions for a contract.\n\nReplaces all existing distributions with the provided list.\nMaximum 6 distributions.\n\nBusiness Rules:\n- Either all absolute values must sum to total commission\n- Or all percentages must sum to 100%","operationId":"batch_update_commissions_api_contracts__contract_id__commissions_put","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommissionDistributionBatchUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CommissionDistributionResponse"},"title":"Response Batch Update Commissions Api Contracts  Contract Id  Commissions Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/commissions/{commission_id}":{"put":{"tags":["Contracts - Protected"],"summary":"Update Contract Commission","description":"Update a commission distribution.","operationId":"update_contract_commission_api_contracts__contract_id__commissions__commission_id__put","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"commission_id","in":"path","required":true,"schema":{"type":"integer","title":"Commission Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommissionDistributionUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommissionDistributionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Contracts - Protected"],"summary":"Delete Contract Commission","description":"Delete a commission distribution.","operationId":"delete_contract_commission_api_contracts__contract_id__commissions__commission_id__delete","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"commission_id","in":"path","required":true,"schema":{"type":"integer","title":"Commission Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/history":{"get":{"tags":["Contracts - Protected"],"summary":"Get Contract History","description":"Get contract state change history.\n\nReturns list of state changes with timestamps and user names.","operationId":"get_contract_history_api_contracts__contract_id__history_get","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/proposta":{"patch":{"tags":["Contracts - Protected"],"summary":"Link Proposal","description":"Link a paid proposal to a contract.\nBody: { propostaId: int }","operationId":"link_proposal_api_contracts__contract_id__proposta_patch","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contracts/{contract_id}/comissao-total":{"get":{"tags":["Contracts - Protected"],"summary":"Get Commission Total","description":"Get the calculated commission total for a contract.\nReturns: { comissaoTotal: float }","operationId":"get_commission_total_api_contracts__contract_id__comissao_total_get","parameters":[{"name":"contract_id","in":"path","required":true,"schema":{"type":"integer","title":"Contract Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pontos-venda/me":{"get":{"tags":["pontos-venda-protected"],"summary":"Get My Ponto Venda","description":"Get full details for the authenticated user's primary PV.\nReturns all PV fields including addresses and emails.","operationId":"get_my_ponto_venda_api_pontos_venda_me_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PontoVendaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pontos-venda/detail/{pv_id}":{"get":{"tags":["pontos-venda-protected"],"summary":"Get Ponto Venda Protected","description":"Get full details for a specific PV (protected endpoint).\nEnforces tenant isolation via company_id.","operationId":"get_ponto_venda_protected_api_pontos_venda_detail__pv_id__get","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PontoVendaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pontos-venda/":{"post":{"tags":["pontos-venda-protected"],"summary":"Create Ponto Venda","description":"Create a new point of sale (protected endpoint).\n\nPerforms multi-table transaction:\n- Creates PV record\n- Creates primary address\n- Creates main and financial emails\n- Creates associated Cliente record\n- Creates payment method\n- Subscribes to plan\n- Creates legal act record\n- Uploads document templates\n- Logs audit trail\n\nRequires: Authentication\nReturns: Created PV object with all details","operationId":"create_ponto_venda_api_pontos_venda__post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PontoVendaCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PontoVendaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pontos-venda/{pv_id}":{"put":{"tags":["pontos-venda-protected"],"summary":"Update Ponto Venda","description":"Update an existing point of sale (protected endpoint).\n\nPerforms multi-table updates:\n- Updates PV record\n- Updates addresses if needed\n- Updates emails if needed\n- Updates invoice series\n- Logs audit trail\n\nRequires: Authentication\nReturns: Updated PV object","operationId":"update_ponto_venda_api_pontos_venda__pv_id__put","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PontoVendaUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PontoVendaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["pontos-venda-protected"],"summary":"Delete Ponto Venda","description":"Point-of-sale deletion is disabled for tenant users.\n\nDeleting a PV makes historical data (leads, credit logs, exports,\nvehicles, financials) go stale, so no company user — not even an admin —\nmay delete a Ponto de Venda. system_admin escape hatches live in\napp/routes/admin.py. Raised OUTSIDE any try/except so it surfaces as a\n403, not a swallowed 500.","operationId":"delete_ponto_venda_api_pontos_venda__pv_id__delete","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pontos-venda/me/credits":{"get":{"tags":["pontos-venda-protected"],"summary":"Get My Credits","description":"Get credit balance for authenticated user's point of sale.\n\nRequires: Authentication\nReturns: Credit balance in euros","operationId":"get_my_credits_api_pontos_venda_me_credits_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pontos-venda/{pv_id}/credits":{"get":{"tags":["pontos-venda-protected"],"summary":"Get Pv Credits","description":"Get credit balance for a specific point of sale (protected endpoint).\n\nRequires: Authentication\nReturns: Credit balance in euros","operationId":"get_pv_credits_api_pontos_venda__pv_id__credits_get","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pontos-venda/{pv_id}/upload-documents":{"post":{"tags":["pontos-venda-protected"],"summary":"Upload Pv Documents","description":"Upload template declaration documents for a point of sale.\n\nThis endpoint:\n- Fetches declaration templates\n- Downloads from S3\n- Re-uploads to PV-specific folder\n- Creates audit trail\n\nRequires: Authentication + Permission to manage documents\nReturns: List of uploaded document URLs\n\nNote: S3 integration required - implement in service layer","operationId":"upload_pv_documents_api_pontos_venda__pv_id__upload_documents_post","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"empresa_id","in":"query","required":true,"schema":{"type":"integer","description":"Company ID","title":"Empresa Id"},"description":"Company ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DocumentUploadResponse"},"title":"Response Upload Pv Documents Api Pontos Venda  Pv Id  Upload Documents Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pontos-venda/{pv_id}/location":{"put":{"tags":["pontos-venda-protected"],"summary":"Set GPS coordinates for a POS","description":"Admin sets latitude/longitude for a POS.\nRequires: { \"latitude\": float, \"longitude\": float }","operationId":"api_set_pos_location_api_pontos_venda__pv_id__location_put","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["pontos-venda-protected"],"summary":"Get GPS coordinates for a POS","description":"Get the stored GPS coordinates and geofence radius for a POS.","operationId":"api_get_pos_location_api_pontos_venda__pv_id__location_get","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pontos-venda/{pv_id}/geocode":{"post":{"tags":["pontos-venda-protected"],"summary":"Auto-geocode POS from address","description":"Geocode a POS's address (MORADA + CODPOST + LOCALIDADE) using OpenStreetMap.\nStores the resulting lat/lng on PontosDeVenda.","operationId":"api_geocode_pos_api_pontos_venda__pv_id__geocode_post","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/create":{"post":{"tags":["Integrazu Adverts"],"summary":"Create Advert","description":"Create a new vehicle advert in Integrazu.\n\n**Integrazu Endpoint:** `POST /api/vehicles/adverts/create`\n\nArgs:\n    advert_data: Complete advert payload with vehicle specifications\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Created advert response with advert ID\n\nExample payload:\n```json\n{\n    \"brand_id\": 51,\n    \"model_id\": 2018,\n    \"fuel_id\": 16,\n    \"category_id\": 8,\n    \"color_id\": 2,\n    \"gearbox_id\": 1,\n    \"mileage\": 35000,\n    \"power\": 116,\n    \"engine_capacity\": 1197,\n    \"first_registration_month\": 3,\n    \"first_registration_year\": 2017,\n    \"price\": 19500,\n    \"registration\": \"42-XI-26\",\n    \"location_id\": \"41\",\n    \"features\": [428, 287, 447]\n}\n```","operationId":"create_advert_api_integrazu_adverts_create_post","parameters":[{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrazuAdvertCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Advert Api Integrazu Adverts Create Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/update/{advert_id}":{"put":{"tags":["Integrazu Adverts"],"summary":"Update Advert","description":"Update an existing vehicle advert in Integrazu.\n\n**Integrazu Endpoint:** `PUT /api/vehicles/adverts/update/{id}`\n\nArgs:\n    advert_id: Integrazu advert ID\n    advert_data: Fields to update (only include changed fields)\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Updated advert response","operationId":"update_advert_api_integrazu_adverts_update__advert_id__put","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrazuAdvertUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Advert Api Integrazu Adverts Update  Advert Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/read/{advert_id}":{"get":{"tags":["Integrazu Adverts"],"summary":"Read Advert","description":"Read/fetch an existing advert from Integrazu.\n\n**Integrazu Endpoint:** `GET /api/vehicles/adverts/read/{id}`\n\nArgs:\n    advert_id: Integrazu advert ID\n    brand_id: Brand ID to fetch the correct Integrazu token\n    listing_id: Optional ViaturasEasyDataGreen.ID to include website exports\n\nReturns:\n    Full advert data including:\n    - exports: Platform exports from Integrazu\n    - website_exports: Website exports from Z_WebsiteExports (if listing_id provided)","operationId":"read_advert_api_integrazu_adverts_read__advert_id__get","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"listing_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"ViaturasEasyDataGreen.ID to fetch website exports","title":"Listing Id"},"description":"ViaturasEasyDataGreen.ID to fetch website exports"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Read Advert Api Integrazu Adverts Read  Advert Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/by-listing/{listing_id}":{"get":{"tags":["Integrazu Adverts"],"summary":"Read Advert By Listing","description":"Read advert by ViaturasEasyDataGreen.ID (listing_id).\n\nThis endpoint:\n1. Looks up Z_PortalExports to find the Integrazu advert ID (portal_object_id)\n2. Fetches the advert from Integrazu\n3. Includes website exports from Z_WebsiteExports\n\nArgs:\n    listing_id: ViaturasEasyDataGreen.ID\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Full advert data including:\n    - exports: Platform exports from Integrazu\n    - website_exports: Website exports from Z_WebsiteExports","operationId":"read_advert_by_listing_api_integrazu_adverts_by_listing__listing_id__get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","title":"Listing Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Read Advert By Listing Api Integrazu Adverts By Listing  Listing Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/getAllAds":{"get":{"tags":["Integrazu Adverts"],"summary":"Get All Ads","description":"Get all adverts for the authenticated client from Integrazu.\n\n**Integrazu Endpoint:** `GET /api/vehicles/adverts/getAllAds`\n\nArgs:\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    List of all adverts","operationId":"get_all_ads_api_integrazu_adverts_getAllAds_get","parameters":[{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get All Ads Api Integrazu Adverts Getallads Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/publish/{advert_id}":{"post":{"tags":["Integrazu Adverts"],"summary":"Publish Advert To Platform","description":"Publish an advert to a specific platform.\n\n**Integrazu Endpoint:** `POST /api/vehicles/adverts/publish/{id}`\n\nArgs:\n    advert_id: Integrazu advert ID\n    body: Platform name (standvirtual, olx, autosapo, carmine, hellocar, etc.)\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Publish operation response\n\nExample payload:\n```json\n{\"platform\": \"standvirtual\"}\n```","operationId":"publish_advert_to_platform_api_integrazu_adverts_publish__advert_id__post","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrazuPublishRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Publish Advert To Platform Api Integrazu Adverts Publish  Advert Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/unpublish/{advert_id}":{"delete":{"tags":["Integrazu Adverts"],"summary":"Unpublish Advert From Platform","description":"Unpublish an advert from a specific platform.\n\n**Integrazu Endpoint:** `DELETE /api/vehicles/adverts/unpublish/{id}`\n\nArgs:\n    advert_id: Integrazu advert ID\n    body: Platform name to unpublish from\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Unpublish operation response\n\nExample payload:\n```json\n{\"platform\": \"autosapo_v2\"}\n```","operationId":"unpublish_advert_from_platform_api_integrazu_adverts_unpublish__advert_id__delete","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrazuPublishRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unpublish Advert From Platform Api Integrazu Adverts Unpublish  Advert Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/republish/{advert_id}":{"post":{"tags":["Integrazu Adverts"],"summary":"Republish Advert On Platform","description":"Republish an advert to refresh its listing on a platform.\n\n**Integrazu Endpoint:** `POST /api/vehicles/adverts/republish/{id}`\n\nArgs:\n    advert_id: Integrazu advert ID\n    body: Platform name to republish on\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Republish operation response\n\nExample payload:\n```json\n{\"platform\": \"hellocar\"}\n```","operationId":"republish_advert_on_platform_api_integrazu_adverts_republish__advert_id__post","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrazuPublishRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Republish Advert On Platform Api Integrazu Adverts Republish  Advert Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/promotion/{advert_id}":{"post":{"tags":["Integrazu Adverts"],"summary":"Promote Advert On Platform","description":"Promote/boost an advert on a platform.\n\n**Integrazu Endpoint:** `POST /api/vehicles/adverts/promotion/{id}`\n\nArgs:\n    advert_id: Integrazu advert ID\n    body: Platform name to promote on\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Promotion operation response\n\nExample payload:\n```json\n{\"platform\": \"hellocar\"}\n```","operationId":"promote_advert_on_platform_api_integrazu_adverts_promotion__advert_id__post","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrazuPublishRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Promote Advert On Platform Api Integrazu Adverts Promotion  Advert Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/images/{advert_id}":{"post":{"tags":["Integrazu Adverts"],"summary":"Add Images To Advert","description":"Add images to an advert.\n\n**Integrazu Endpoint:** `POST /api/vehicles/adverts/images/{id}`\n\nArgs:\n    advert_id: Integrazu advert ID\n    body: List of image URLs to upload\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Image upload response\n\nExample payload:\n```json\n{\n    \"images\": [\n        \"https://example.com/image1.jpg\",\n        \"https://example.com/image2.jpg\"\n    ]\n}\n```","operationId":"add_images_to_advert_api_integrazu_adverts_images__advert_id__post","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrazuImageUploadRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add Images To Advert Api Integrazu Adverts Images  Advert Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Integrazu Adverts"],"summary":"Delete Images From Advert","description":"Delete all images from an advert.\n\n**Integrazu Endpoint:** `DELETE /api/vehicles/adverts/images/{id}`\n\nArgs:\n    advert_id: Integrazu advert ID\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Image deletion response","operationId":"delete_images_from_advert_api_integrazu_adverts_images__advert_id__delete","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Images From Advert Api Integrazu Adverts Images  Advert Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/photos/{advert_id}":{"post":{"tags":["Integrazu Adverts"],"summary":"Sync Photos To Platform","description":"Sync/refresh advert photos on a specific platform.\n\n**Integrazu Endpoint:** `POST /api/vehicles/adverts/photos/{id}`\n\nUse this after adding/updating images to push them to a platform.\n\nArgs:\n    advert_id: Integrazu advert ID\n    body: Platform name to sync photos on\n    brand_id: Brand ID to fetch the correct Integrazu token\n\nReturns:\n    Photo sync response\n\nExample payload:\n```json\n{\"platform\": \"autosapo_v2\"}\n```","operationId":"sync_photos_to_platform_api_integrazu_adverts_photos__advert_id__post","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrazuPublishRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sync Photos To Platform Api Integrazu Adverts Photos  Advert Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/adverts/sync-status/by-vehicle/{vehicle_id}":{"get":{"tags":["Integrazu Adverts"],"summary":"Check Sync Status By Vehicle","description":"Check sync status between ViaturasEasyDataGreen and Integrazu advert by vehicle ID.\n\nThis endpoint:\n1. Fetches the listing from ViaturasEasyDataGreen by vehicle_id (idviatura)\n2. Transforms it to Integrazu format using listing_to_integrazu()\n3. Looks up the Integrazu advert ID from Z_PortalExports\n4. Fetches the current advert from Integrazu\n5. Compares all fields and returns differences\n\nArgs:\n    vehicle_id: Viatura.ID (idviatura column in ViaturasEasyDataGreen)\n    brand_id: Z_Brands.id for token lookup\n    pv_id: PontosDeVenda.ID for Integrazu location_id lookup\n\nReturns:\n    {\n        \"synced\": bool,\n        \"vehicle_id\": int,\n        \"listing_id\": int,\n        \"integrazu_advert_id\": int,\n        \"differences\": [\n            {\n                \"field\": \"price\",\n                \"display_name\": \"Preco\",\n                \"local_value\": 19500,\n                \"integrazu_value\": 18000\n            },\n            ...\n        ],\n        \"local_payload\": {...},\n        \"integrazu_payload\": {...}\n    }","operationId":"check_sync_status_by_vehicle_api_integrazu_adverts_sync_status_by_vehicle__vehicle_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for token lookup","title":"Brand Id"},"description":"Z_Brands.id for token lookup"},{"name":"pv_id","in":"query","required":true,"schema":{"type":"integer","description":"PontosDeVenda.ID for location lookup","title":"Pv Id"},"description":"PontosDeVenda.ID for location lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Check Sync Status By Vehicle Api Integrazu Adverts Sync Status By Vehicle  Vehicle Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/clear-cache":{"post":{"tags":["Integrazu Data"],"summary":"Clear Cache","description":"Clear all cached Integrazu data. Forces fresh fetch on next request.","operationId":"clear_cache_api_integrazu_data_clear_cache_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/sections":{"get":{"tags":["Integrazu Data"],"summary":"Get Sections","description":"Get vehicle sections (Cars, Motorcycles, Boats, etc.).\n\nSections are the top-level vehicle category.\nUsed as starting point for brand/model selection.","operationId":"get_sections_api_integrazu_data_sections_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Sections Api Integrazu Data Sections Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/colors":{"get":{"tags":["Integrazu Data"],"summary":"Get Colors","description":"Get all available vehicle colors.","operationId":"get_colors_api_integrazu_data_colors_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Colors Api Integrazu Data Colors Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/gearboxes":{"get":{"tags":["Integrazu Data"],"summary":"Get Gearboxes","description":"Get all gearbox types (Manual, Automatic, CVT, etc.).\n\nNote: This returns the base list. Use /catalog/gearboxes for\nfiltered options based on vehicle specs.","operationId":"get_gearboxes_api_integrazu_data_gearboxes_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Gearboxes Api Integrazu Data Gearboxes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/gearbox-shifts":{"get":{"tags":["Integrazu Data"],"summary":"Get Gearbox Shifts","description":"Get gearbox shift types (Manual, Semi-Automatic, Automatic).","operationId":"get_gearbox_shifts_api_integrazu_data_gearbox_shifts_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Gearbox Shifts Api Integrazu Data Gearbox Shifts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/traction":{"get":{"tags":["Integrazu Data"],"summary":"Get Traction","description":"Get traction types (FWD, RWD, AWD, 4WD).","operationId":"get_traction_api_integrazu_data_traction_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Traction Api Integrazu Data Traction Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/registrations":{"get":{"tags":["Integrazu Data"],"summary":"Get Registrations","description":"Get registration types (New, Used, Imported, etc.).","operationId":"get_registrations_api_integrazu_data_registrations_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Registrations Api Integrazu Data Registrations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/origins":{"get":{"tags":["Integrazu Data"],"summary":"Get Origins","description":"Get vehicle origins (National, Imported).","operationId":"get_origins_api_integrazu_data_origins_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Origins Api Integrazu Data Origins Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/classes":{"get":{"tags":["Integrazu Data"],"summary":"Get Classes","description":"Get vehicle classes (Economy, Compact, Luxury, etc.).","operationId":"get_classes_api_integrazu_data_classes_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Classes Api Integrazu Data Classes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/conditions":{"get":{"tags":["Integrazu Data"],"summary":"Get Conditions","description":"Get vehicle conditions (New, Used, Certified Pre-Owned, etc.).","operationId":"get_conditions_api_integrazu_data_conditions_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Conditions Api Integrazu Data Conditions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/batteries":{"get":{"tags":["Integrazu Data"],"summary":"Get Batteries","description":"Get battery types and specifications (for electric/hybrid vehicles).","operationId":"get_batteries_api_integrazu_data_batteries_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Batteries Api Integrazu Data Batteries Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/battery-type":{"get":{"tags":["Integrazu Data"],"summary":"Get Battery Types","description":"Get battery type options (for electric/hybrid vehicles).","operationId":"get_battery_types_api_integrazu_data_battery_type_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Battery Types Api Integrazu Data Battery Type Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/brake-energy-recovery":{"get":{"tags":["Integrazu Data"],"summary":"Get Brake Energy Recovery","description":"Get brake energy recovery options (for electric/hybrid vehicles).","operationId":"get_brake_energy_recovery_api_integrazu_data_brake_energy_recovery_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Brake Energy Recovery Api Integrazu Data Brake Energy Recovery Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/charging-connector-type":{"get":{"tags":["Integrazu Data"],"summary":"Get Charging Connector Types","description":"Get charging connector type options (for electric vehicles).","operationId":"get_charging_connector_types_api_integrazu_data_charging_connector_type_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Charging Connector Types Api Integrazu Data Charging Connector Type Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/type-of-current":{"get":{"tags":["Integrazu Data"],"summary":"Get Type Of Current","description":"Get type of current options (AC/DC for electric vehicles).","operationId":"get_type_of_current_api_integrazu_data_type_of_current_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Type Of Current Api Integrazu Data Type Of Current Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/platforms":{"get":{"tags":["Integrazu Data"],"summary":"Get Platforms","description":"Get advertising platforms (StandVirtual, OLX, Autosapo, etc.).","operationId":"get_platforms_api_integrazu_data_platforms_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Platforms Api Integrazu Data Platforms Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/brands-platforms":{"get":{"tags":["Integrazu Data"],"summary":"Get Brands With Platforms","description":"Get brand + PV configuration with available Integrazu platforms.\n\n**pv_id is REQUIRED** - filters by specific Point of Sale.\n\nReturns exactly ONE entry per brand of the company, carrying that brand's\nIntegrazu export state FOR THE REQUESTED PV.\n\n`export_state` is the discriminator the Export tab keys its layout off:\n\n  \"brand_unprovisioned\"   no Integrazu_Creds row for (brand, company).\n                          platforms=[]. Rendered in the grouped\n                          \"Marcas nao configuradas\" card.\n  \"location_unconfigured\" creds exist, but this PV has no usable\n                          Z_PortalExportTokens row (idportal=13). The brand\n                          HAS an Integrazu account; the point of sale was\n                          never wired to an Integrazu location. Rendered as\n                          the \"localizacao nao configurada\" banner.\n  \"configured\"            ready to publish from this PV; `platforms` carries\n                          the brand account's real per-portal `enabled`.\n\n⛔ In the \"location_unconfigured\" state `platforms` still carries the whole\nglobal catalog force-flagged `enabled: false`. That is a DELIBERATE\ncompatibility shim for the deploy window, not the state's meaning — the\nnew FE ignores it. See the inline comment on that branch before changing it.\n\n⛔ `pv_id` in the response is always the REQUESTED pv. The matched token\nrow's own id_pv is `token_pv_id` (None when a brand-wide row was used), and\n`token_scope` says which tier matched (\"pv\" | \"brand\" | None).\n\nArgs:\n    pv_id: PontosDeVenda.ID (required). NOTE: not ownership-checked here —\n           it is only ever used as a filter, and `pv_name` is resolved with\n           an `IDempresa = b.idcompany` predicate so a foreign pv_id yields\n           pv_name=None rather than leaking another tenant's PV name.\n\nReturns:\n    [\n        {\n            \"brand_id\": 1,\n            \"brand_name\": \"Stand ABC\",\n            \"provisioned\": true,\n            \"export_state\": \"configured\",\n            \"location_configured\": true,\n            \"token_scope\": \"pv\",\n            \"pv_id\": 10,\n            \"token_pv_id\": 10,\n            \"pv_name\": \"Lisboa Centro\",\n            \"integrazu_location_id\": \"539\",\n            \"website_id\": 5,\n            \"website_domain\": \"standabc.pt\",\n            \"platforms\": [\n                {\"id\": 1, \"slug\": \"standvirtual\", \"designation\": \"StandVirtual\", \"enabled\": true},\n                {\"id\": 2, \"slug\": \"olx\", \"designation\": \"OLX\", \"enabled\": true},\n                ...\n            ]\n        }\n    ]","operationId":"get_brands_with_platforms_api_integrazu_data_brands_platforms_get","parameters":[{"name":"pv_id","in":"query","required":true,"schema":{"type":"integer","description":"Point of Sale ID (required)","title":"Pv Id"},"description":"Point of Sale ID (required)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Brands With Platforms Api Integrazu Data Brands Platforms Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/brands-portals":{"get":{"tags":["Integrazu Data"],"summary":"Get Brands With Portals Company Wide","description":"Company-scoped brand+portal catalog for the per-brand portal settings page.\n\nUnlike /brands-platforms, this endpoint does NOT require a PV: it lists every\nbrand belonging to the authenticated company together with the full global\nportal catalog. Status per (brand, portal) comes from a separate call to\nGET /integrazu/portal-config/status; this endpoint only returns the catalog.\n\nUsed by /settings/portals so a company can submit portal credentials at the\nbrand level (pv_id = NULL in Z_BrandPortalConfigurations) without first\nneeding a vehicle.\n\nReturns:\n    [\n        {\n            \"brand_id\": 1,\n            \"brand_name\": \"Stand ABC\",\n            \"portals\": [\n                {\"id\": 1, \"slug\": \"standvirtual\", \"designation\": \"StandVirtual\", \"logo\": \"...\", \"enabled\": False},\n                ...\n            ]\n        }\n    ]","operationId":"get_brands_with_portals_company_wide_api_integrazu_data_brands_portals_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Brands With Portals Company Wide Api Integrazu Data Brands Portals Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/brands-websites":{"get":{"tags":["Integrazu Data"],"summary":"Get Brands Websites","description":"Get all brands for the company with their available websites.\n\nEach brand has one website (Z_Brands.idwebsite -> Websites.id).\nUse this endpoint to populate the \"export to websites\" selection in the UI.\n\nReturns:\n    List of brands with website info:\n    [\n        {\n            \"brand_id\": 1,\n            \"brand_name\": \"Stand ABC\",\n            \"website_id\": 5,\n            \"website_domain\": \"standabc.pt\"\n        },\n        {\n            \"brand_id\": 2,\n            \"brand_name\": \"Stand XYZ\",\n            \"website_id\": 8,\n            \"website_domain\": \"standxyz.pt\"\n        }\n    ]","operationId":"get_brands_websites_api_integrazu_data_brands_websites_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Brands Websites Api Integrazu Data Brands Websites Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/locations":{"get":{"tags":["Integrazu Data"],"summary":"Get Locations","description":"Get dealership locations registered in Integrazu.","operationId":"get_locations_api_integrazu_data_locations_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Locations Api Integrazu Data Locations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/brands/{section_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Brands","description":"Get vehicle brands for a specific section.\n\nArgs:\n    section_id: Section ID (e.g., 1=Cars, 2=Motorcycles)","operationId":"get_brands_api_integrazu_data_brands__section_id__get","parameters":[{"name":"section_id","in":"path","required":true,"schema":{"type":"integer","title":"Section Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Brands Api Integrazu Data Brands  Section Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/categories/{section_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Categories","description":"Get vehicle categories for a section (SUV, Sedan, Hatchback, etc.).\n\nArgs:\n    section_id: Section ID","operationId":"get_categories_api_integrazu_data_categories__section_id__get","parameters":[{"name":"section_id","in":"path","required":true,"schema":{"type":"integer","title":"Section Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Categories Api Integrazu Data Categories  Section Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/features/{section_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Features","description":"Get available features/options for a section.\n\nFeatures include: ABS, Air Conditioning, Leather Seats, Navigation, etc.\n\nArgs:\n    section_id: Section ID","operationId":"get_features_api_integrazu_data_features__section_id__get","parameters":[{"name":"section_id","in":"path","required":true,"schema":{"type":"integer","title":"Section Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Features Api Integrazu Data Features  Section Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/doors/{section_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Doors","description":"Get door count options for a section.\n\nNote: This returns base door options. Use /catalog/doors for\nfiltered options based on model specs.\n\nArgs:\n    section_id: Section ID","operationId":"get_doors_api_integrazu_data_doors__section_id__get","parameters":[{"name":"section_id","in":"path","required":true,"schema":{"type":"integer","title":"Section Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Doors Api Integrazu Data Doors  Section Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/capacity/{section_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Capacity","description":"Get seating capacity options for a section.\n\nArgs:\n    section_id: Section ID","operationId":"get_capacity_api_integrazu_data_capacity__section_id__get","parameters":[{"name":"section_id","in":"path","required":true,"schema":{"type":"integer","title":"Section Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Capacity Api Integrazu Data Capacity  Section Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/fuels/{section_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Fuels","description":"Get fuel types available for a section.\n\nNote: This returns all fuel types for the section.\nUse /catalog/fuels/{model_id} for model-specific options.\n\nArgs:\n    section_id: Section ID","operationId":"get_fuels_api_integrazu_data_fuels__section_id__get","parameters":[{"name":"section_id","in":"path","required":true,"schema":{"type":"integer","title":"Section Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Fuels Api Integrazu Data Fuels  Section Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/models/{brand_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Models","description":"Get vehicle models for a specific brand.\n\nArgs:\n    brand_id: Brand ID (e.g., BMW, Audi, Toyota)","operationId":"get_models_api_integrazu_data_models__brand_id__get","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"integer","title":"Brand Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Models Api Integrazu Data Models  Brand Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/versions/{model_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Versions","description":"Get all versions/trims for a specific model.\n\nNote: This returns all versions. Use /catalog/versions for\nfiltered versions based on complete specs.\n\nArgs:\n    model_id: Model ID","operationId":"get_versions_api_integrazu_data_versions__model_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Versions Api Integrazu Data Versions  Model Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/districts":{"get":{"tags":["Integrazu Data"],"summary":"Get Districts","description":"Get all Portuguese districts (top-level geographic division).","operationId":"get_districts_api_integrazu_data_districts_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Districts Api Integrazu Data Districts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/counties/{district_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Counties","description":"Get counties (concelhos) within a district.\n\nArgs:\n    district_id: District ID","operationId":"get_counties_api_integrazu_data_counties__district_id__get","parameters":[{"name":"district_id","in":"path","required":true,"schema":{"type":"integer","title":"District Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Counties Api Integrazu Data Counties  District Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/parishes/{county_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Parishes","description":"Get parishes (freguesias) within a county.\n\nThis is the most granular geographic level.\n\nArgs:\n    county_id: County ID","operationId":"get_parishes_api_integrazu_data_parishes__county_id__get","parameters":[{"name":"county_id","in":"path","required":true,"schema":{"type":"integer","title":"County Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Parishes Api Integrazu Data Parishes  County Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/catalog/fuels/{model_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Fuels By Model Old","description":"Get fuel types available for a specific model (old path).","operationId":"get_fuels_by_model_old_api_integrazu_data_catalog_fuels__model_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"is_imported_car","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Imported flag (0 or 1)","title":"Is Imported Car"},"description":"Imported flag (0 or 1)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Fuels By Model Old Api Integrazu Data Catalog Fuels  Model Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/data/catalog/versions/{model_id}/{fuel_id}/{gearbox_id}":{"get":{"tags":["Integrazu Data"],"summary":"Get Versions Catalog Old","description":"Get vehicle versions filtered by specs (old path).","operationId":"get_versions_catalog_old_api_integrazu_data_catalog_versions__model_id___fuel_id___gearbox_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"gearbox_id","in":"path","required":true,"schema":{"type":"integer","title":"Gearbox Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"engine_power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine power in HP","title":"Engine Power"},"description":"Engine power in HP"},{"name":"engine_capacity","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine capacity in cc","title":"Engine Capacity"},"description":"Engine capacity in cc"},{"name":"door_count","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Number of doors","title":"Door Count"},"description":"Number of doors"},{"name":"is_imported_car","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Imported flag (0 or 1)","title":"Is Imported Car"},"description":"Imported flag (0 or 1)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Versions Catalog Old Api Integrazu Data Catalog Versions  Model Id   Fuel Id   Gearbox Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/catalog/engine-powers/{model_id}/{fuel_id}":{"get":{"tags":["Vehicles Data Catalog"],"summary":"Get Engine Powers","description":"Get available engine power options for model and fuel.\n\nReturns list of engine power values (HP) with IDs.","operationId":"get_engine_powers_api_vehicles_data_catalog_engine_powers__model_id___fuel_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"is_imported_car","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Imported flag (0 or 1)","title":"Is Imported Car"},"description":"Imported flag (0 or 1)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Engine Powers Api Vehicles Data Catalog Engine Powers  Model Id   Fuel Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/catalog/engine-capacities/{model_id}/{fuel_id}":{"get":{"tags":["Vehicles Data Catalog"],"summary":"Get Engine Capacities","description":"Get engine capacities filtered by model, fuel, year, and power.\n\nReturns list of engine capacity options (cc) with IDs.","operationId":"get_engine_capacities_api_vehicles_data_catalog_engine_capacities__model_id___fuel_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"engine_power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine power in HP","title":"Engine Power"},"description":"Engine power in HP"},{"name":"is_imported_car","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Imported flag (0 or 1)","title":"Is Imported Car"},"description":"Imported flag (0 or 1)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Engine Capacities Api Vehicles Data Catalog Engine Capacities  Model Id   Fuel Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/catalog/doors/{model_id}/{fuel_id}":{"get":{"tags":["Vehicles Data Catalog"],"summary":"Get Doors Catalog","description":"Get door count options filtered by model, fuel, year, power, and engine capacity.\n\nReturns list of door count options with IDs.","operationId":"get_doors_catalog_api_vehicles_data_catalog_doors__model_id___fuel_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"engine_power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine power in HP","title":"Engine Power"},"description":"Engine power in HP"},{"name":"engine_capacity","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine capacity in cc","title":"Engine Capacity"},"description":"Engine capacity in cc"},{"name":"is_imported_car","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Imported flag (0 or 1)","title":"Is Imported Car"},"description":"Imported flag (0 or 1)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Doors Catalog Api Vehicles Data Catalog Doors  Model Id   Fuel Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/catalog/gearboxes/{model_id}/{fuel_id}":{"get":{"tags":["Vehicles Data Catalog"],"summary":"Get Gearboxes Catalog","description":"Get gearbox options filtered by all previous selections.\n\nReturns list of gearbox options with IDs.","operationId":"get_gearboxes_catalog_api_vehicles_data_catalog_gearboxes__model_id___fuel_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"engine_power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine power in HP","title":"Engine Power"},"description":"Engine power in HP"},{"name":"engine_capacity","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine capacity in cc","title":"Engine Capacity"},"description":"Engine capacity in cc"},{"name":"door_count","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Number of doors","title":"Door Count"},"description":"Number of doors"},{"name":"is_imported_car","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Imported flag (0 or 1)","title":"Is Imported Car"},"description":"Imported flag (0 or 1)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Gearboxes Catalog Api Vehicles Data Catalog Gearboxes  Model Id   Fuel Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/catalog/fuels/{model_id}":{"get":{"tags":["Vehicles Data Catalog"],"summary":"Get Fuels By Model","description":"Get fuel types available for a specific model.\n\nThis returns model-specific fuel options (more filtered than /fuels/{section_id}).\n\n**VERIFIED WORKING** - This endpoint exists in Integrazu API.","operationId":"get_fuels_by_model_api_vehicles_data_catalog_fuels__model_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"is_imported_car","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Imported flag (0 or 1)","title":"Is Imported Car"},"description":"Imported flag (0 or 1)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Fuels By Model Api Vehicles Data Catalog Fuels  Model Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicles/data/catalog/versions/{model_id}/{fuel_id}/{gearbox_id}":{"get":{"tags":["Vehicles Data Catalog"],"summary":"Get Versions Catalog","description":"Get vehicle versions filtered by model, fuel, gearbox, and optional specs.\n\n**VERIFIED WORKING** - This endpoint exists in Integrazu API.\n\nReturns specific vehicle versions matching the provided specifications.\nFilter results client-side by `active` field (active == 1).\n\nArgs:\n    model_id: Vehicle model ID\n    fuel_id: Fuel type ID (from catalog/fuels)\n    gearbox_id: Gearbox type ID (from static /gearboxes)\n    year: Optional registration year filter\n    engine_power: Optional power filter\n    engine_capacity: Optional capacity filter\n    door_count: Optional door count filter\n    is_imported_car: Optional import flag (0 or 1)\n\nReturns:\n    List of versions with {id, designation, active} structure","operationId":"get_versions_catalog_api_vehicles_data_catalog_versions__model_id___fuel_id___gearbox_id__get","parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"integer","title":"Model Id"}},{"name":"fuel_id","in":"path","required":true,"schema":{"type":"integer","title":"Fuel Id"}},{"name":"gearbox_id","in":"path","required":true,"schema":{"type":"integer","title":"Gearbox Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"First registration year","title":"Year"},"description":"First registration year"},{"name":"engine_power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine power in HP","title":"Engine Power"},"description":"Engine power in HP"},{"name":"engine_capacity","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Engine capacity in cc","title":"Engine Capacity"},"description":"Engine capacity in cc"},{"name":"door_count","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Number of doors","title":"Door Count"},"description":"Number of doors"},{"name":"is_imported_car","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Imported flag (0 or 1)","title":"Is Imported Car"},"description":"Imported flag (0 or 1)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Versions Catalog Api Vehicles Data Catalog Versions  Model Id   Fuel Id   Gearbox Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/publish/start":{"post":{"tags":["Integrazu Publishing Jobs"],"summary":"Start Publishing Job","description":"Start vehicle publishing workflow(s) - supports multiple brands.\n\nCreates one job per brand. Each brand has its own Integrazu token and location,\nso each requires a separate advert creation and publishing flow.\n\n**Request Format:**\n```json\n{\n    \"vehicle_id\": 1234,\n    \"brands\": [\n        {\"brand_id\": 5, \"platforms\": [\"standvirtual\", \"olx\"], \"location_id\": \"539\"},\n        {\"brand_id\": 8, \"platforms\": [\"carmine\"], \"location_id\": \"742\"}\n    ],\n    \"advert_data\": { ... },\n    \"image_urls\": [\"https://...\"]\n}\n```\n\n**Setup:**\n- Use GET /api/integrazu/data/brands-platforms to get brands with their location_ids and available platforms\n\n**Workflow (per brand):**\n- \"A criar anuncio\"\n- \"A carregar imagens\" (if image_urls provided)\n- \"A publicar em {Platform}\" (for each platform)\n\n**Error Handling:**\n- Each brand's job is independent - if one fails, others continue\n- Within a job: if advert creation fails, that job fails\n- If image upload fails: continues with publishing\n- If a portal fails: continues with remaining portals\n\n**Polling:**\nUse GET /api/integrazu/publish/{job_id} for each job_id returned","operationId":"start_publishing_job_api_integrazu_publish_start_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishJobCreateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishJobCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/publish/{job_id}":{"get":{"tags":["Integrazu Publishing Jobs"],"summary":"Get Publishing Job Status","description":"Get the current status of a publishing job.\n\nReturns detailed information including:\n- Overall job status and progress percentage\n- Current step being executed\n- Status of each individual step (create, upload, publish to each platform)\n- Error messages for failed steps\n- Summary of succeeded vs failed platforms\n\n**Status Values:**\n- `pending` - Job created but not yet started\n- `processing` - Actively processing steps\n- `completed` - All steps finished (check platforms_succeeded/failed)\n- `failed` - Job failed (critical error, e.g., advert creation failed)\n- `retrying` - Retrying failed steps\n\n**Step Status Values:**\n- `pending` - Not yet started\n- `in_progress` - Currently executing\n- `completed` - Finished successfully\n- `failed` - Failed (see error_message)\n- `skipped` - Skipped (e.g., no images to upload)","operationId":"get_publishing_job_status_api_integrazu_publish__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishJobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/publish/vehicle/{vehicle_id}":{"get":{"tags":["Integrazu Publishing Jobs"],"summary":"Get Vehicle Publishing Jobs","description":"Get recent publishing jobs for a vehicle.\n\nReturns the most recent jobs ordered by created_at descending.","operationId":"get_vehicle_publishing_jobs_api_integrazu_publish_vehicle__vehicle_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"default":10,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishJobListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/adverts/read/{advert_id}":{"get":{"tags":["StandVirtual Adverts"],"summary":"Sv Read Advert","description":"Read an advert from StandVirtual API.","operationId":"sv_read_advert_api_standvirtual_adverts_read__advert_id__get","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/adverts/update/{advert_id}":{"put":{"tags":["StandVirtual Adverts"],"summary":"Sv Update Advert","description":"Update an existing advert on StandVirtual.\nRequires full payload (same structure as create).\nNote: make/model/year are locked after 24h.","operationId":"sv_update_advert_api_standvirtual_adverts_update__advert_id__put","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/adverts/activate/{advert_id}":{"post":{"tags":["StandVirtual Adverts"],"summary":"Sv Activate Advert","description":"Activate an advert on StandVirtual.","operationId":"sv_activate_advert_api_standvirtual_adverts_activate__advert_id__post","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/adverts/deactivate/{advert_id}":{"post":{"tags":["StandVirtual Adverts"],"summary":"Sv Deactivate Advert","description":"Deactivate an advert (temporary — can be reactivated).","operationId":"sv_deactivate_advert_api_standvirtual_adverts_deactivate__advert_id__post","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/adverts/delete/{advert_id}":{"delete":{"tags":["StandVirtual Adverts"],"summary":"Sv Delete Advert","description":"Delete an advert permanently (irreversible).","operationId":"sv_delete_advert_api_standvirtual_adverts_delete__advert_id__delete","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/adverts/promote-olx/{advert_id}":{"post":{"tags":["StandVirtual Adverts"],"summary":"Sv Promote Olx","description":"Export advert to OLX via promotions. Must be activated first.","operationId":"sv_promote_olx_api_standvirtual_adverts_promote_olx__advert_id__post","parameters":[{"name":"advert_id","in":"path","required":true,"schema":{"type":"integer","title":"Advert Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/adverts/by-listing/{listing_id}":{"get":{"tags":["StandVirtual Adverts"],"summary":"Sv Get By Listing","description":"Lookup StandVirtual Direct export record by listing ID.\n\nReturns the Z_PortalExports record (integrazu=0) if it exists.","operationId":"sv_get_by_listing_api_standvirtual_adverts_by_listing__listing_id__get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","title":"Listing Id"}},{"name":"id_brand","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Brand"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/data/clear-cache":{"post":{"tags":["StandVirtual Data"],"summary":"Clear Cache","description":"Clear all cached StandVirtual catalog data.","operationId":"clear_cache_api_standvirtual_data_clear_cache_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/data/makes":{"get":{"tags":["StandVirtual Data"],"summary":"Sv Get Makes","description":"Get all makes for a category.","operationId":"sv_get_makes_api_standvirtual_data_makes_get","parameters":[{"name":"category_id","in":"query","required":false,"schema":{"type":"integer","description":"Category ID (29=cars, 73=commercial)","default":29,"title":"Category Id"},"description":"Category ID (29=cars, 73=commercial)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/data/models/{make_code}":{"get":{"tags":["StandVirtual Data"],"summary":"Sv Get Models","description":"Get models for a make.","operationId":"sv_get_models_api_standvirtual_data_models__make_code__get","parameters":[{"name":"make_code","in":"path","required":true,"schema":{"type":"string","title":"Make Code"}},{"name":"category_id","in":"query","required":false,"schema":{"type":"integer","default":29,"title":"Category Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/data/engine-codes/{make_code}/{model_code}":{"get":{"tags":["StandVirtual Data"],"summary":"Sv Get Engine Codes","description":"Get engine codes for a model (required for BMW/Mercedes/Lexus/Porsche).","operationId":"sv_get_engine_codes_api_standvirtual_data_engine_codes__make_code___model_code__get","parameters":[{"name":"make_code","in":"path","required":true,"schema":{"type":"string","title":"Make Code"}},{"name":"model_code","in":"path","required":true,"schema":{"type":"string","title":"Model Code"}},{"name":"category_id","in":"query","required":false,"schema":{"type":"integer","default":29,"title":"Category Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/data/fuel-types/{make_code}/{model_code}":{"get":{"tags":["StandVirtual Data"],"summary":"Sv Get Fuel Types","description":"Get fuel types for a model (with year + imported filters).","operationId":"sv_get_fuel_types_api_standvirtual_data_fuel_types__make_code___model_code__get","parameters":[{"name":"make_code","in":"path","required":true,"schema":{"type":"string","title":"Make Code"}},{"name":"model_code","in":"path","required":true,"schema":{"type":"string","title":"Model Code"}},{"name":"year","in":"query","required":true,"schema":{"type":"integer","description":"Registration year","title":"Year"},"description":"Registration year"},{"name":"is_imported","in":"query","required":false,"schema":{"type":"string","description":"Is imported car (0 or 1)","default":"0","title":"Is Imported"},"description":"Is imported car (0 or 1)"},{"name":"category_id","in":"query","required":false,"schema":{"type":"integer","default":29,"title":"Category Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/data/versions/{make_code}/{model_code}":{"get":{"tags":["StandVirtual Data"],"summary":"Sv Get Versions","description":"Get versions via full cascade chain (v=2).","operationId":"sv_get_versions_api_standvirtual_data_versions__make_code___model_code__get","parameters":[{"name":"make_code","in":"path","required":true,"schema":{"type":"string","title":"Make Code"}},{"name":"model_code","in":"path","required":true,"schema":{"type":"string","title":"Model Code"}},{"name":"year","in":"query","required":true,"schema":{"type":"integer","title":"Year"}},{"name":"fuel_type","in":"query","required":true,"schema":{"type":"string","title":"Fuel Type"}},{"name":"engine_power","in":"query","required":true,"schema":{"type":"string","title":"Engine Power"}},{"name":"engine_capacity","in":"query","required":true,"schema":{"type":"string","title":"Engine Capacity"}},{"name":"door_count","in":"query","required":false,"schema":{"type":"string","default":"4","title":"Door Count"}},{"name":"gearbox","in":"query","required":false,"schema":{"type":"string","default":"manual","title":"Gearbox"}},{"name":"is_imported","in":"query","required":false,"schema":{"type":"string","default":"0","title":"Is Imported"}},{"name":"category_id","in":"query","required":false,"schema":{"type":"integer","default":29,"title":"Category Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/publish/start":{"post":{"tags":["StandVirtual Publish"],"summary":"Sv Start Publish","description":"Start a StandVirtual Direct publish workflow.\n\nCreates a background job that:\n1. Resolves catalog codes (make/model → SV string codes)\n2. Creates image collection (if image_urls provided)\n3. Creates advert on StandVirtual\n4. Activates advert\n5. Exports to OLX (if export_olx=true)\n\nReturns job_id for progress polling.\n\nBody:\n{\n    \"vehicle_id\": 123,          (required) Viatura.ID\n    \"listing_id\": 456,          (required) ViaturasEasyDataGreen.ID\n    \"id_brand\": 1,              (optional) Z_Brands.id for portal tracking\n    \"image_urls\": [...],        (optional) List of image URLs\n    \"export_olx\": false,        (optional) Also export to OLX\n    \"use_catalog_version\": false, (optional) Use v=2 catalog version\n    \"contact_name\": \"Multigest\", (optional) Contact name\n    \"category_id\": 29           (optional) 29=cars, 73=commercial\n}","operationId":"sv_start_publish_api_standvirtual_publish_start_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/publish/{job_id}":{"get":{"tags":["StandVirtual Publish"],"summary":"Sv Get Job","description":"Get job status with all steps.","operationId":"sv_get_job_api_standvirtual_publish__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standvirtual/publish/vehicle/{vehicle_id}":{"get":{"tags":["StandVirtual Publish"],"summary":"Sv Get Vehicle Jobs","description":"Get recent publish jobs for a vehicle.","operationId":"sv_get_vehicle_jobs_api_standvirtual_publish_vehicle__vehicle_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/adverts/by-listing/{listing_id}":{"get":{"tags":["Pisca-Pisca Adverts"],"summary":"Pp Get By Listing","description":"Lookup Pisca-Pisca Direct export record by listing ID.\n\nReturns the Z_PortalExports record (integrazu=0, id_portal=5) if it exists.","operationId":"pp_get_by_listing_api_piscapisca_adverts_by_listing__listing_id__get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"integer","title":"Listing Id"}},{"name":"id_brand","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Brand"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/clear-cache":{"post":{"tags":["Pisca-Pisca Data"],"summary":"Clear Cache","description":"Clear all cached Pisca-Pisca catalog data.","operationId":"clear_cache_api_piscapisca_data_clear_cache_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/stands":{"get":{"tags":["Pisca-Pisca Data"],"summary":"Pp Get Stands","description":"Get Pisca-Pisca stands for the configured account.","operationId":"pp_get_stands_api_piscapisca_data_stands_get","parameters":[{"name":"id_brand","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for credential lookup","title":"Id Brand"},"description":"Z_Brands.id for credential lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/brands":{"get":{"tags":["Pisca-Pisca Data"],"summary":"Pp Get Brands","description":"Get all vehicle brands from Pisca-Pisca catalog.","operationId":"pp_get_brands_api_piscapisca_data_brands_get","parameters":[{"name":"id_brand","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for credential lookup","title":"Id Brand"},"description":"Z_Brands.id for credential lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/models/{brand_id}":{"get":{"tags":["Pisca-Pisca Data"],"summary":"Pp Get Models","description":"Get models for a brand.","operationId":"pp_get_models_api_piscapisca_data_models__brand_id__get","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"string","title":"Brand Id"}},{"name":"id_brand","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for credential lookup","title":"Id Brand"},"description":"Z_Brands.id for credential lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/series/{brand_id}/{model_id}":{"get":{"tags":["Pisca-Pisca Data"],"summary":"Pp Get Series","description":"Get series/versions for a model.","operationId":"pp_get_series_api_piscapisca_data_series__brand_id___model_id__get","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"string","title":"Brand Id"}},{"name":"model_id","in":"path","required":true,"schema":{"type":"string","title":"Model Id"}},{"name":"id_brand","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for credential lookup","title":"Id Brand"},"description":"Z_Brands.id for credential lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/fuels":{"get":{"tags":["Pisca-Pisca Data"],"summary":"Pp Get Fuels","description":"Get fuel types.","operationId":"pp_get_fuels_api_piscapisca_data_fuels_get","parameters":[{"name":"id_brand","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for credential lookup","title":"Id Brand"},"description":"Z_Brands.id for credential lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/types":{"get":{"tags":["Pisca-Pisca Data"],"summary":"Pp Get Types","description":"Get vehicle types.","operationId":"pp_get_types_api_piscapisca_data_types_get","parameters":[{"name":"id_brand","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for credential lookup","title":"Id Brand"},"description":"Z_Brands.id for credential lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/transmissions":{"get":{"tags":["Pisca-Pisca Data"],"summary":"Pp Get Transmissions","description":"Get transmission types.","operationId":"pp_get_transmissions_api_piscapisca_data_transmissions_get","parameters":[{"name":"id_brand","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for credential lookup","title":"Id Brand"},"description":"Z_Brands.id for credential lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/tractions":{"get":{"tags":["Pisca-Pisca Data"],"summary":"Pp Get Tractions","description":"Get traction types.","operationId":"pp_get_tractions_api_piscapisca_data_tractions_get","parameters":[{"name":"id_brand","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for credential lookup","title":"Id Brand"},"description":"Z_Brands.id for credential lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/data/colors":{"get":{"tags":["Pisca-Pisca Data"],"summary":"Pp Get Colors","description":"Get color options.","operationId":"pp_get_colors_api_piscapisca_data_colors_get","parameters":[{"name":"id_brand","in":"query","required":true,"schema":{"type":"integer","description":"Z_Brands.id for credential lookup","title":"Id Brand"},"description":"Z_Brands.id for credential lookup"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/publish/start":{"post":{"tags":["Pisca-Pisca Publish"],"summary":"Pp Start Publish","description":"Start a Pisca-Pisca Direct publish workflow.\n\nCreates a background job that:\n1. Resolves catalog codes (names → PP encoded IDs)\n2. Skips image upload (not yet available)\n3. Creates vehicle on Pisca-Pisca\n\nReturns job_id for progress polling.\n\nBody:\n{\n    \"vehicle_id\": 123,          (required) Viatura.ID\n    \"listing_id\": 456,          (required) ViaturasEasyDataGreen.ID\n    \"id_brand\": 1,              (required) Z_Brands.id\n}","operationId":"pp_start_publish_api_piscapisca_publish_start_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/publish/{job_id}":{"get":{"tags":["Pisca-Pisca Publish"],"summary":"Pp Get Job","description":"Get job status with all steps.","operationId":"pp_get_job_api_piscapisca_publish__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/piscapisca/publish/vehicle/{vehicle_id}":{"get":{"tags":["Pisca-Pisca Publish"],"summary":"Pp Get Vehicle Jobs","description":"Get recent publish jobs for a vehicle.","operationId":"pp_get_vehicle_jobs_api_piscapisca_publish_vehicle__vehicle_id__get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/portal-config/schema":{"get":{"tags":["Portal Schema"],"summary":"Get Portal Config Schema","description":"slug -> {title, description, helpUrl, helpText, fields[]} map (cached 6h).","operationId":"get_portal_config_schema_api_integrazu_portal_config_schema_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/portal-config/schema/clear-cache":{"post":{"tags":["Portal Schema"],"summary":"Clear Schema Cache","description":"Force a refresh of the cached portal schema.","operationId":"clear_schema_cache_api_integrazu_portal_config_schema_clear_cache_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/portal-config":{"post":{"tags":["Portal Configuration"],"summary":"Submit Portal Config","description":"Submit or update portal credentials for a brand+portal combination.\n\nPayload from PortalConfigDialog.js:\n{\n    \"brand_id\": 1,\n    \"pv_id\": 10,  (optional)\n    \"platform_slug\": \"standvirtual\",\n    \"credentials\": { \"client_id\": \"...\", \"client_secret\": \"...\", ... }\n}\n\nA support ticket is opened for every submission so the work is tracked\nrather than living only in an email — see app/services/portal_config_tickets.\n\nGOVERNING PRINCIPLE: the credentials are the product, the ticket is the\nalert. Nothing in the alerting path may prevent the credentials from being\nstored, so every lookup that can fail (PV ownership, company name, ticket\ncreation) lives AFTER the upsert and is individually guarded. The response\nis a 200 with `ticket_id: null` when the alert degrades — never a 4xx/5xx\non a submission that succeeded.","operationId":"submit_portal_config_api_integrazu_portal_config_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Portal Configuration"],"summary":"List Portal Configs","description":"List portal configurations for the authenticated company. Credentials masked.","operationId":"list_portal_configs_api_integrazu_portal_config_get","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Brand Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/portal-config/status":{"get":{"tags":["Portal Configuration"],"summary":"Get Portal Config Statuses","description":"Get status summary for ExportTab display.\nReturns: { brand_id: { portal_id: \"pending\"|\"active\"|... } }","operationId":"get_portal_config_statuses_api_integrazu_portal_config_status_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/portal-config/credentials":{"get":{"tags":["Portal Configuration"],"summary":"Get Portal Config Credentials","description":"Pre-fill payload for the \"Configurar\" dialog of an already-submitted portal.\n\nReturns identifier fields (client_id/username/prefix/email) in plaintext so the\nform can pre-populate them, plus a filled/not-filled boolean per true secret —\nsecret values are NEVER returned. Tenant-guarded by company.\n\npv_id is accepted for symmetry with the dialog but not used for lookup: a\nconfig row is keyed by (brand, portal, company), so it's resolved brand-level.","operationId":"get_portal_config_credentials_api_integrazu_portal_config_credentials_get","parameters":[{"name":"brand_id","in":"query","required":true,"schema":{"type":"integer","title":"Brand Id"}},{"name":"portal_slug","in":"query","required":true,"schema":{"type":"string","title":"Portal Slug"}},{"name":"pv_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/portal-config/request-email":{"post":{"tags":["Portal Configuration"],"summary":"Send Credential Request Email","description":"Send a credential request email that the user receives and forwards to the\nportal entity. The recipient is the point of sale's email when `pv_id` is\ngiven (vehicle ad export flow); otherwise — the brand-level flow used by\n/settings/portais, which has no PV in scope — it goes to the requesting\nuser's own email.\n\nPayload:\n{\n    \"pv_id\": 10,          # optional — omit for the brand-level flow\n    \"brand_id\": 1,\n    \"portal_slug\": \"standvirtual\",\n    \"portal_title\": \"StandVirtual\",\n    \"required_fields\": [\"Client ID\", \"Client Secret\", \"Username\", \"Password\"]\n}","operationId":"send_credential_request_email_api_integrazu_portal_config_request_email_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/portal-config/{config_id}":{"get":{"tags":["Portal Configuration"],"summary":"Get Portal Config Detail","description":"Get single portal configuration detail. Credentials masked.","operationId":"get_portal_config_detail_api_integrazu_portal_config__config_id__get","parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"integer","title":"Config Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/integrazu/location-config/requests":{"post":{"tags":["Export Location Requests"],"summary":"Request Export Location","description":"Ask Multigest to configure a point of sale for ad export.\n\nBody: {\"pv_id\": int, \"brand_ids\": [int, ...]}\n\n`brand_ids` is plural because several brands of the same company can be\nblocked on the SAME point of sale; the tab groups them into one banner and\nthis endpoint into ONE ticket, rather than N near-identical ones.\n\nReturns 200 {\"ticket_id\", \"status\", \"pv_id\", \"pv_name\", \"brand_ids\"}.\n\nRefusals (the ticket IS the product here — never a silent success):\n    400 invalid input / no identifiable user / open-ticket ceiling\n    403 brand or PV does not belong to the caller's company\n    409 brand not provisioned at all, or location already configured,\n        or a request is already open (carries `ticket_id`)\n    429 duplicate press debounced","operationId":"request_export_location_api_integrazu_location_config_requests_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Export Location Requests"],"summary":"List Export Location Requests","description":"Open location-configuration requests for the caller's company, keyed by\nbrand id so the Export tab can render \"Aguarda configuração\" in place of the\nrequest button.\n\nShape mirrors GET /integrazu/portal-config/status so the FE pattern is\nidentical:\n    {\"2\": {\"ticket_id\": 1234, \"status\": \"open\", \"pv_id\": 138,\n           \"requested_at\": \"2026-08-25T10:04:00\"}}\n\nJSON object keys are strings, so brand ids are stringified.\n\n⚠️ `pv_id` NARROWS the tenant guard, it never replaces it\n(02-security.md §1) — idcompany always comes from the session.\n\n⚠️ Non-critical by design: the FE swallows failures here and simply shows\nthe request button. In particular, if the DDL has not been applied yet this\nendpoint fails while the Export tab itself keeps working, because\nget_brands_for_company() deliberately does not reference the new table.","operationId":"list_export_location_requests_api_integrazu_location_config_requests_get","parameters":[{"name":"pv_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Narrow to one point of sale","title":"Pv Id"},"description":"Narrow to one point of sale"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/check-nif":{"get":{"tags":["Clients - Protected"],"summary":"Check NIF duplicate","description":"Check if a NIF (Portuguese or foreign) is already linked to a client\nin the same company. Matches against both Cliente.NIF and Cliente.foreign_NIF.","operationId":"check_nif_api_clients_check_nif_get","parameters":[{"name":"nif","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":50,"description":"NIF (Portuguese 9-digit or foreign alphanumeric) to check","title":"Nif"},"description":"NIF (Portuguese 9-digit or foreign alphanumeric) to check"},{"name":"exclude_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Client ID to exclude (for updates)","title":"Exclude Id"},"description":"Client ID to exclude (for updates)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NifCheckResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/vies-lookup":{"get":{"tags":["Clients - Protected"],"summary":"Look up a NIF/VAT in the EU VIES registry","description":"Resolve a NIF/VAT into the registered trader's name and parsed address.\n\nRead-only, no DB access — async handler is safe here (no pyodbc work) and\nkeeps the blocking external call off the shared threadpool.","operationId":"vies_lookup_api_clients_vies_lookup_get","parameters":[{"name":"nif","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":50,"description":"PT NIF (9 digits) or EU VAT with country prefix (e.g. ESB85937712)","title":"Nif"},"description":"PT NIF (9 digits) or EU VAT with country prefix (e.g. ESB85937712)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViesLookupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/auto-from-nif":{"post":{"tags":["Clients - Protected"],"summary":"Auto-create a client from VIES registry data","description":"Create the client for a NIF using its VIES-registered name/address, when\nit doesn't exist yet in the company (invoice-insertion auto-create). The\nclient is created with no email/contacto — allowed, since both are optional.\nAlways returns 200 with a structured outcome; the FE branches on\ncreated/exists/reason. Plain `def` — it does DB work in the threadpool.","operationId":"auto_from_nif_api_clients_auto_from_nif_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoFromNifRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoFromNifResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/combos/estados-civis":{"get":{"tags":["Clients - Protected"],"summary":"Get civil status options","description":"Get estado civil dropdown options.","operationId":"get_estados_civis_combo_api_clients_combos_estados_civis_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EstadoCivilComboItem"},"title":"Response Get Estados Civis Combo Api Clients Combos Estados Civis Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/combos/tipos-casa":{"get":{"tags":["Clients - Protected"],"summary":"Get house type options","description":"Get tipo casa dropdown options.","operationId":"get_tipos_casa_combo_api_clients_combos_tipos_casa_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TipoCasaComboItem"},"title":"Response Get Tipos Casa Combo Api Clients Combos Tipos Casa Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/combos/contratos-trabalho":{"get":{"tags":["Clients - Protected"],"summary":"Get employment contract options","description":"Get contrato trabalho dropdown options.","operationId":"get_contratos_trabalho_combo_api_clients_combos_contratos_trabalho_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContratoTrabalhoComboItem"},"title":"Response Get Contratos Trabalho Combo Api Clients Combos Contratos Trabalho Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/combos/tipos-cliente":{"get":{"tags":["Clients - Protected"],"summary":"Get client type options","description":"Get tipo cliente dropdown options.","operationId":"get_tipos_cliente_combo_api_clients_combos_tipos_cliente_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TipoClienteComboItem"},"title":"Response Get Tipos Cliente Combo Api Clients Combos Tipos Cliente Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/by-email":{"get":{"tags":["Clients - Protected"],"summary":"Find client by email address","description":"Find a client by email via the polymorphic Emails table.","operationId":"get_client_by_email_endpoint_api_clients_by_email_get","parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","description":"Email address to search","title":"Email"},"description":"Email address to search"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/combo":{"get":{"tags":["Clients - Protected"],"summary":"Lightweight client list for dropdowns","description":"Lightweight client list for Autocomplete dropdowns.\n\nReturns only ID, Nome, NIF, contacto — no COUNT query, no aggregations.","operationId":"clients_combo_api_clients_combo_get","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by name, NIF, or phone","title":"Search"},"description":"Search by name, NIF, or phone"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients":{"get":{"tags":["Clients - Protected"],"summary":"List clients","description":"List clients with pagination and filters.\nResults are scoped to the authenticated user's company.\nDeactivated clients are hidden unless include_inactive=true.","operationId":"list_clients_api_clients_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of records to skip","default":0,"title":"Skip"},"description":"Number of records to skip"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Maximum records to return","default":50,"title":"Limit"},"description":"Maximum records to return"},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by name, NIF, email, or phone","title":"Q"},"description":"Search by name, NIF, email, or phone"},{"name":"pv_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by point of sale ID","title":"Pv Id"},"description":"Filter by point of sale ID"},{"name":"particular","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by individual (true) or company (false)","title":"Particular"},"description":"Filter by individual (true) or company (false)"},{"name":"recorrente","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by recurring client","title":"Recorrente"},"description":"Filter by recurring client"},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort order: 'id_desc' for newest first","title":"Sort"},"description":"Sort order: 'id_desc' for newest first"},{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","description":"Include deactivated clients (ativo=0)","default":false,"title":"Include Inactive"},"description":"Include deactivated clients (ativo=0)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Clients Api Clients Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Clients - Protected"],"summary":"Create client","description":"Create a new client with proper data separation.\n\nThis endpoint follows the correct client creation pattern:\n1. Client basic info goes to Cliente table (nome, nif, contacto, etc.)\n2. Email goes to Emails table (id_modulo=12, id_modulo_id=client_id)\n3. Address goes to Moradas table (id_modulo=12, id_modulo_id=client_id)\n\nAutomatically assigns the client to the authenticated user's company.\nValidates NIF uniqueness within the company.","operationId":"create_client_api_clients_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/{client_id}":{"get":{"tags":["Clients - Protected"],"summary":"Get client by ID","description":"Get single client with all details and addresses.\nVerifies the client belongs to the authenticated user's company.","operationId":"get_client_api_clients__client_id__get","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Client ID","title":"Client Id"},"description":"Client ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Clients - Protected"],"summary":"Update client","description":"Update an existing client.\nVerifies the client belongs to the authenticated user's company.\nValidates NIF uniqueness if NIF is being changed.","operationId":"update_client_api_clients__client_id__put","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Client ID","title":"Client Id"},"description":"Client ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Clients - Protected"],"summary":"Deactivate client","description":"Deactivate a client/supplier (soft-delete: ativo=0). Reversible via\nPOST /{client_id}/reactivate. Kept on the DELETE verb so existing callers\nkeep working; the client just disappears from lists/pickers while the name\nstill resolves in the history. Verifies company ownership (IDempresa).","operationId":"delete_client_api_clients__client_id__delete","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Client ID","title":"Client Id"},"description":"Client ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/{client_id}/reactivate":{"post":{"tags":["Clients - Protected"],"summary":"Reactivate client","description":"Reactivate a previously-deactivated client/supplier (ativo=1).\nVerifies the client belongs to the authenticated user's company (IDempresa).","operationId":"reactivate_client_api_clients__client_id__reactivate_post","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Client ID","title":"Client Id"},"description":"Client ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/{client_id}/addresses":{"get":{"tags":["Clients - Protected"],"summary":"List client addresses","description":"List all addresses for a client.","operationId":"list_addresses_api_clients__client_id__addresses_get","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Client ID","title":"Client Id"},"description":"Client ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AddressResponse"},"title":"Response List Addresses Api Clients  Client Id  Addresses Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Clients - Protected"],"summary":"Add address","description":"Add a new address to a client.","operationId":"create_address_api_clients__client_id__addresses_post","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Client ID","title":"Client Id"},"description":"Client ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/{client_id}/addresses/{address_id}":{"put":{"tags":["Clients - Protected"],"summary":"Update address","description":"Update an existing address.","operationId":"update_address_api_clients__client_id__addresses__address_id__put","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Client ID","title":"Client Id"},"description":"Client ID"},{"name":"address_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Address ID","title":"Address Id"},"description":"Address ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Clients - Protected"],"summary":"Delete address","description":"Delete an address.","operationId":"delete_address_api_clients__client_id__addresses__address_id__delete","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Client ID","title":"Client Id"},"description":"Client ID"},{"name":"address_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"Address ID","title":"Address Id"},"description":"Address ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/ocr-document":{"post":{"tags":["Clients - Protected"],"summary":"Ler Cartão de Cidadão (frente+verso) e devolver campos para autofill do cliente","description":"OCR a Portuguese Cartão de Cidadão via Claude Vision and return the storable\nclient fields (nome, nif, nº documento, validade, entidade emissora) for the\ncreate-client form to prefill. Data-minimized: no DOB/sex/filiação/NISS.\n\nRGPD: this route reads the images in-memory and never persists them. When the\nclient is created, the frontend attaches them as Documentos do cliente (módulo\n12, tipo CC) via POST /documents-test/ — same retention as a manual upload.\nUnreadable/unsupported input returns success=False (never a 5xx); billing only\nfires on success. Heavy sync work runs in the threadpool (same pattern as\n/vehicles/ocr-document).","operationId":"ocr_citizen_card_api_clients_ocr_document_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_ocr_citizen_card_api_clients_ocr_document_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CitizenCardOcrResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/clients/ocr-driving-license":{"post":{"tags":["Clients - Protected"],"summary":"Ler Carta de Condução e devolver campos para autofill do cliente","description":"OCR a Portuguese Carta de Condução via Claude Vision and return the storable\nclient fields (nome, nº da carta, data de emissão) plus the card's validade,\nwhich only stamps DataExpira on the attached document. Data-minimized: no DOB,\nno nº de identificação civil, no categorias.\n\nRGPD: reads the images in-memory and never persists them; the frontend attaches\nthem as Documentos do cliente (módulo 12, tipo \"Carta de Condução\") after the\nclient is saved. Unreadable/unsupported input returns success=False (never a\n5xx); billing only fires on success, and success requires the document to\nactually be a licence. Heavy sync work runs in the threadpool.","operationId":"ocr_driving_license_api_clients_ocr_driving_license_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_ocr_driving_license_api_clients_ocr_driving_license_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrivingLicenseOcrResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/change-requests":{"get":{"tags":["Sócios (Protected)"],"summary":"Listar pedidos de alteração","operationId":"list_change_requests_api_socios_change_requests_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"PENDING | APPROVED | REJECTED | EXPIRED | APPLIED","title":"Status"},"description":"PENDING | APPROVED | REJECTED | EXPIRED | APPLIED"},{"name":"requested_by","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Requested By"}},{"name":"target_partner_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Target Partner Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Change Requests Api Socios Change Requests Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/change-requests/pending-for-me":{"get":{"tags":["Sócios (Protected)"],"summary":"Pedidos pendentes do meu voto","operationId":"list_pending_for_me_api_socios_change_requests_pending_for_me_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Pending For Me Api Socios Change Requests Pending For Me Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/change-requests/{request_id}":{"get":{"tags":["Sócios (Protected)"],"summary":"Detalhe de um pedido de alteração","operationId":"get_change_request_api_socios_change_requests__request_id__get","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Request Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/change-requests/{request_id}/vote":{"post":{"tags":["Sócios (Protected)"],"summary":"Votar num pedido de alteração","operationId":"vote_api_socios_change_requests__request_id__vote_post","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Request Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/change-requests/{request_id}/cancel":{"post":{"tags":["Sócios (Protected)"],"summary":"Cancelar um pedido pendente","operationId":"cancel_api_socios_change_requests__request_id__cancel_post","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Request Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios":{"get":{"tags":["Sócios (Protected)"],"summary":"Listar sócios da empresa","operationId":"list_partners_api_socios_get","parameters":[{"name":"active","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"}},{"name":"utilizador_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Utilizador Id"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Search"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PartnerResponse"},"title":"Response List Partners Api Socios Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Sócios (Protected)"],"summary":"Criar sócio (submete pedido de alteração)","operationId":"create_partner_api_socios_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/pv-roster":{"post":{"tags":["Sócios (Protected)"],"summary":"Substituir o quadro de sócios num ponto de venda (pedido único)","description":"Bundled change request: close every currently-active agreement at the\ntarget PV and replace with the rows in the payload, all in one approval\ncycle. Avoids the validation deadlock that occurs when DELETE + CREATE\nare submitted as four independent requests.","operationId":"replace_pv_roster_api_socios_pv_roster_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PvRosterReplaceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/{partner_id}":{"get":{"tags":["Sócios (Protected)"],"summary":"Detalhe de um sócio","operationId":"get_partner_api_socios__partner_id__get","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Sócios (Protected)"],"summary":"Atualizar sócio (submete pedido de alteração)","operationId":"update_partner_api_socios__partner_id__put","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Sócios (Protected)"],"summary":"Eliminar sócio (soft delete via pedido de alteração)","operationId":"delete_partner_api_socios__partner_id__delete","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/{partner_id}/agreements":{"get":{"tags":["Sócios (Protected)"],"summary":"Listar acordos do sócio (inclui histórico)","operationId":"list_agreements_api_socios__partner_id__agreements_get","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"active","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"}},{"name":"idpointofsale","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idpointofsale"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Agreements Api Socios  Partner Id  Agreements Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Sócios (Protected)"],"summary":"Criar acordo (submete pedido de alteração)","operationId":"create_agreement_api_socios__partner_id__agreements_post","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgreementCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/{partner_id}/agreements/{agreement_id}":{"put":{"tags":["Sócios (Protected)"],"summary":"Atualizar acordo (close-and-replace via pedido)","operationId":"update_agreement_api_socios__partner_id__agreements__agreement_id__put","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"agreement_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Agreement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgreementUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Sócios (Protected)"],"summary":"Fechar acordo (submete pedido de alteração)","operationId":"delete_agreement_api_socios__partner_id__agreements__agreement_id__delete","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"agreement_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Agreement Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRequestSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/reports/lucros":{"get":{"tags":["Sócios (Relatórios)"],"summary":"Relatório anual de lucros por sócio","description":"Per-partner 12-month grid of profit share at a PV. The agreement %\nused for each month is the one active on the last day of that month.\nMovements attributable to vehicles whose contract is suspended\n(Contratos.IDestado = 3) are excluded — project-wide rule.","operationId":"report_lucros_year_api_socios_reports_lucros_get","parameters":[{"name":"pv","in":"query","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"ID do ponto de venda","title":"Pv"},"description":"ID do ponto de venda"},{"name":"year","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Year"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Report Lucros Year Api Socios Reports Lucros Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/reports/movimentos-year":{"get":{"tags":["Sócios (Relatórios)"],"summary":"Relatório anual de movimentos por sócio","description":"Per-partner 12-month grid of total partner-movement value at a PV\n(pivot of MovimentosSocios → Movimentos.ValorTotal).","operationId":"report_movimentos_year_api_socios_reports_movimentos_year_get","parameters":[{"name":"pv","in":"query","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Pv"}},{"name":"year","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Year"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Report Movimentos Year Api Socios Reports Movimentos Year Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/reports/partners-at-pv":{"get":{"tags":["Sócios (Relatórios)"],"summary":"Sócios ativos num ponto de venda (para filtros de relatório)","description":"Returns the partners active TODAY at the given PV — used to\npopulate the partner Autocomplete in the reports filter bar. The\nexisting /financeiro/partners/active endpoint is scoped to the\nuser's own PV (via auth claim); admin reports need to pick any PV\nin the company.","operationId":"report_partners_at_pv_api_socios_reports_partners_at_pv_get","parameters":[{"name":"pv","in":"query","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Pv"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Report Partners At Pv Api Socios Reports Partners At Pv Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/socios/reports/movimentos-month":{"get":{"tags":["Sócios (Relatórios)"],"summary":"Detalhe mensal de movimentos de um sócio","description":"Detail rows of one partner's attributed movements for a given\n(PV, year, month). Returns `{items, total_count, total_sum, offset,\nlimit}` — `total_sum` mirrors the legacy SumOfValorTotal subquery.","operationId":"report_movimentos_month_api_socios_reports_movimentos_month_get","parameters":[{"name":"pv","in":"query","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Pv"}},{"name":"year","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Year"}},{"name":"month","in":"query","required":true,"schema":{"type":"integer","maximum":12,"minimum":1,"title":"Month"}},{"name":"partner_id","in":"query","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Partner Id"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Report Movimentos Month Api Socios Reports Movimentos Month Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/permissions/catalog":{"get":{"tags":["Permissions"],"summary":"Company-assignable permission catalogue grouped by resource","description":"Return the permission actions a company admin may assign, grouped by\nresource for a frontend matrix. Hard-excludes system_admin and platform\n(admin:*) actions. If this is near-empty, run scripts/map_endpoint_actions.py\n--seed --apply to populate Z_Permissions with the derived action set.","operationId":"get_permission_catalog_api_permissions_catalog_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/permissions/assignable-roles":{"get":{"tags":["Permissions"],"summary":"List roles that can be assigned by company admins","description":"Roles a company admin may assign — THEIR company's, minus any that\ntransitively grant a NEVER_ASSIGNABLE permission.\n\n**On `catalog_router` (gate: `admin`) deliberately, since 2026-07-30.** It\nused to sit on `protected_router`, which carries `system_admin` — while\n`POST /api/invitations` needs only `admin`. A real company admin therefore\ngot a 403 here, the frontend swallowed it into an empty list, the invite\ndialog hid the Role field entirely, and every invitee silently fell through\nto the company's `Completo` copy (all 22 modules). Finding B1, reproduced in\na browser 2026-07-30; see docs/planning/permission-system.md §\"Step 10a-2\".\n\n`admin` is the right bar precisely because it is the gate on the write this\nlist feeds: reading the names of roles you are permitted to assign is\nstrictly weaker than assigning one. Two guards in the body — and not the\nrouter — are what make it sufficient:\n\n1. **Tenant scope.** `idcompany` comes from `request.state.current_user`,\n   never from the client. Every company owns a private copy of the role\n   catalogue, so the pre-2026-07-29 unscoped `list_roles()` handed every\n   admin every other tenant's role names *and ids*, which the assignment\n   endpoints accept.\n2. **No escalation.** Any role carrying a name in\n   `actions.NEVER_ASSIGNABLE` — `system_admin`, `admin`, `view_all_pvs` — is\n   dropped. `GET /company-roles` has no such filter, which is why the invite\n   picker must NOT be repointed at it.\n\n   Filtering on `system_admin` ALONE was not enough once this route moved to\n   `catalog_router`. The audience changed with the gate: on\n   `protected_router` the only readers were Multigest staff, and blocking\n   the one permission they could not already grant themselves was\n   sufficient. On `admin` the readers are every tenant admin, and the set\n   exists precisely because `admin` and `view_all_pvs` are the escalation\n   and cross-PV-data names (see actions.py:88-97). The seeded company copies\n   of `socio` and `Administrador` DO carry the legacy `admin` row, and the\n   consumer of this list writes the chosen role into `Z_UserPvRoles`, which\n   `app/auth.py` reads straight into `pv_permissions` — so offering \"Sócio\"\n   in the invite dialog was offering company-admin rights. The invite\n   endpoint re-checks the same set server-side\n   (`invitations.py::_assert_role_is_assignable`); this filter keeps the\n   picker from showing a choice that can only be refused.\n\nResource `permissions` stays in `PLATFORM_RESOURCES`, so this path carries no\nMODULE gate — on purpose. The invite dialog lives on `/users`\n(`modulo.utilizadores`) and the role editor on `modulo.configuracoes`; module-\ngating this list would 403 an admin who holds one and not the other, which is\nthe same silent-empty-list failure one module over. It is registered in\n`PLATFORM_RESOURCE_TENANT_PATHS` so the coverage test knows it is tenant-facing.\n\nSystem templates are excluded (`include_templates=False`). They belong to no\ncompany, so `assign_role` and `set_user_pv_role` both refuse them — listing\nthem as \"assignable\" offered a choice that could only ever fail.","operationId":"list_assignable_roles_api_permissions_assignable_roles_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roles":{"get":{"tags":["Permissions"],"summary":"List all roles","description":"The platform role catalogue — scopeable, and always LABELLED (F1, 2026-07-30).\n\nThis endpoint feeds the role dropdown of the system-admin user dialogs\n(`RolesPermissionsPage.js`, via `useRolesPermissions.fetchRoles`), and it was\nunscoped: **115 rows on the test DB**, because since 2026-07-29 every company\nowns a private COPY of the catalogue, so the same six names repeat once per\ntenant. The frontend renders them flat with\n`getOptionLabel={(option) => option.name || ''}` — twenty identical entries\nreading \"socio\", of which nineteen belong to somebody else's company. Picking\nthe wrong one was a coin flip, and `PUT /api/admin/users/{id}` then wrote it\nstraight into `Z_Users.idrole`, which `app/auth.py` resolves with no company\nscoping at all. That is what made a cross-tenant `admin` grant a ONE-CLICK\nmistake rather than a deliberate act.\n\nThe write path is now the real guard (`app/db/admin.py`: resolve against the\ntarget row's company, refuse another tenant's role, refuse elevated content\nwithout an explicit confirmation). This endpoint stops the mistake being\n*offered*:\n\n* **`company_id` scopes the list** to that company's own copies plus the\n  system templates (templates are kept because `_resolve_role_for_company`\n  maps a template to the company's copy, so they are legitimately pickable).\n  This is what the user dialogs should pass.\n* **Every row is labelled, unconditionally** — including the unscoped call,\n  which the Roles tab genuinely needs (a `system_admin` managing the whole\n  catalogue). `company_name` and a ready-made `label` are ADDED fields;\n  `name` is left byte-identical on purpose, because the same list backs the\n  Roles tab's edit form and decorating `name` would round-trip the decoration\n  into `Z_Roles.name` on the next save.\n\n`idcompany` was already in the payload and was already ignored by the client;\na name is what makes a foreign pick visible. See the report for the two\none-line frontend changes this enables.\n\n**Also served since 2026-08-27, for the Roles tab clean-up** — all ADDED\nfields, none replacing anything:\n\n* `is_system` / `kind` — from `app/permissions/roles.py`, the SAME functions\n  `GET /api/company-roles` uses. `is_system` alone conflates the two cases\n  whose edit semantics differ (a template, whose rename cascades to every\n  tenant's copy, versus one of those copies, whose name is the template's to\n  set), so `kind` names all four.\n* `holders` — how many people hold the row, from `role_holder_counts()`.\n  In the list because the alternative is 115 round trips on mount, and\n  because the delete confirmation must not be able to show a different\n  number than the guard enforces.\n* `copies` — for a template, how many company copies carry its\n  `template_key`. This is the blast radius of a cascading rename.\n\nThe counts are two grouped queries merged in Python rather than a JOIN\ninside `list_roles`, for the reason `admin_db.get_company_names` already\nrecords: `list_roles`'s scoped form backs `list_assignable_roles`, a TENANT\nroute on the `admin` gate that fires on every invite-dialog open and does\nnot want the cost.","operationId":"list_roles_api_roles_get","parameters":[{"name":"company_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Empresa alvo. Quando indicada, devolve apenas os papéis dessa empresa mais os modelos de sistema — use-a sempre que a lista alimenta um seletor de papel para um utilizador.","title":"Company Id"},"description":"Empresa alvo. Quando indicada, devolve apenas os papéis dessa empresa mais os modelos de sistema — use-a sempre que a lista alimenta um seletor de papel para um utilizador."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Permissions"],"summary":"Create a role for a company","description":"Create a company-owned role.\n\nThe company is REQUIRED and comes from the body — never from the session,\nwhich on a `system_admin` route is whichever tenant the admin last switched\ninto (docs/claude/02-security.md §10).\n\nValidated against `get_company_universe()`, NOT `Empresas`: two active users\ncarry `IDempresa = 2` with no `Empresas` row, and that company owns six live\nrole copies. Refusing it would refuse a real tenant.\n\nDeliberately cannot create a TEMPLATE. A template minted from a dialog has\nan empty `Z_RolePermissions`: fanned out it gives every company a role that\ngrants nothing, not fanned out it gives a template nobody can hold (both\nassignment paths reject templates). The six real templates are versioned\nartefacts of two SQL scripts that would not know about a seventh.\n`template_key` is not accepted either — stamping one on a hand-made role\ndisguises it as a system copy, which locks the tenant out of editing it\n(`_assert_role_is_company_authored`) and stops\n`ensure_company_role_copies` from ever re-creating it.","operationId":"create_role_api_roles_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roles/{role_id}":{"get":{"tags":["Permissions"],"summary":"Get a role by ID","description":"Get a specific role by ID.","operationId":"get_role_api_roles__role_id__get","parameters":[{"name":"role_id","in":"path","required":true,"schema":{"type":"integer","title":"Role Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Permissions"],"summary":"Rename or re-describe a role","description":"Rename / re-describe a role, deliberately and audited.\n\nRenaming a system TEMPLATE cascades to every company copy of it, in one\nstatement (owner decision, 2026-08-27). Template and copies are name-identical\nby construction — `ensure_company_role_copies` copies `t.name` and nothing\nrenames a copy — so letting them diverge would make the list HARDER to read,\nwhich is the problem this work exists to fix.\n\nThree guards, in order:\n\n1. **A no-op writes nothing.** The frontend always sends both fields\n   (`setRoleForm({name: role.name || '', description: role.description || ''})`),\n   so \"unset means unchanged\" is not available — the diff is computed here\n   against the stored row. Without it, opening a template and pressing\n   Guardar would rewrite 19 rows across 18 tenants and file 19 audit rows;\n   and the `|| ''` would write `''` over every NULL description.\n2. **A system row needs `edit_system_role`.** The refusal names the token\n   because `useRolesPermissions.js::isPrivilegedGrantRefusal` distinguishes\n   retryable refusals by `detail` text, not by status code.\n3. **A system COPY may not be renamed at all.** Its name belongs to the\n   template. Allowing it manufactures exactly the divergence the cascade\n   prevents, and there is no way back — `reset-template` only rewrites\n   `modulo.*` rows. The description stays editable.","operationId":"update_role_api_roles__role_id__put","parameters":[{"name":"role_id","in":"path","required":true,"schema":{"type":"integer","title":"Role Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Permissions"],"summary":"Delete a role","description":"Delete a role — only ever a company-authored or a global one.\n\nThe full matrix, and why nothing here is a confirmable 409, is in\n`permissions_db.delete_platform_role_guarded`. In short: a template deleted\nfrom here has no repair path through the product, a system copy comes back\nunder a new id at the next invite, and deleting a HELD role is a company\nlockout rather than an escalation — `get_effective_modules` INNER JOINs\n`Z_Roles`, so the survivors resolve to the empty set.","operationId":"delete_role_api_roles__role_id__delete","parameters":[{"name":"role_id","in":"path","required":true,"schema":{"type":"integer","title":"Role Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/permissions":{"get":{"tags":["Permissions"],"summary":"List all permissions","description":"Get all permissions in the system.","operationId":"list_permissions_api_permissions_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Permissions"],"summary":"Create a new permission","description":"Create a new permission.","operationId":"create_permission_api_permissions_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/permissions/assignable-permissions":{"get":{"tags":["Permissions"],"summary":"List permissions that company admins can assign","description":"List the permissions a company admin may be given.\n\nFilters the single shared `NEVER_ASSIGNABLE` set, not a local copy of it —\nthe copy this used to read still said `{\"system_admin\"}`, so `admin` and\n`view_all_pvs` were both offered as assignable.","operationId":"list_assignable_permissions_api_permissions_assignable_permissions_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/permissions/{permission_id}":{"get":{"tags":["Permissions"],"summary":"Get a permission by ID","description":"Get a specific permission by ID.","operationId":"get_permission_api_permissions__permission_id__get","parameters":[{"name":"permission_id","in":"path","required":true,"schema":{"type":"integer","title":"Permission Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Permissions"],"summary":"Update a permission","description":"Update an existing permission.","operationId":"update_permission_api_permissions__permission_id__put","parameters":[{"name":"permission_id","in":"path","required":true,"schema":{"type":"integer","title":"Permission Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Permissions"],"summary":"Delete a permission","description":"Delete a permission and all its mappings.","operationId":"delete_permission_api_permissions__permission_id__delete","parameters":[{"name":"permission_id","in":"path","required":true,"schema":{"type":"integer","title":"Permission Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roles/{role_id}/permissions":{"get":{"tags":["Permissions"],"summary":"Get permissions for a role","description":"Get all permissions assigned to a specific role.","operationId":"get_role_permissions_api_roles__role_id__permissions_get","parameters":[{"name":"role_id","in":"path","required":true,"schema":{"type":"integer","title":"Role Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Permissions"],"summary":"Add permission to role","description":"Add a single permission to a role.\n\nSame privileged-grant policy as the per-user paths (2026-08-13). Roles were\nthe last outright refusal to fall: the argument for keeping them absolute was\nblast radius, and the answer is to SHOW the blast radius — the 409 names how\nmany people hold the role — rather than to refuse an operation Multigest staff\nlegitimately need.","operationId":"add_role_permission_api_roles__role_id__permissions_post","parameters":[{"name":"role_id","in":"path","required":true,"schema":{"type":"integer","title":"Role Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionAssign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Permissions"],"summary":"Set all permissions for a role","description":"Replace all permissions for a role with the given list.\n\nThe console's role editor. Delta-based like everything else, which is what\nmakes `Administrador` and `socio` editable again: they carry the legacy\n`admin` row, the dialog resubmits it on every save, and the old per-id refusal\nturned that into a permanent 403 on roles whose whole purpose is granting it.","operationId":"set_role_permissions_api_roles__role_id__permissions_put","parameters":[{"name":"role_id","in":"path","required":true,"schema":{"type":"integer","title":"Role Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionsBulkAssign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roles/{role_id}/holders":{"get":{"tags":["Permissions"],"summary":"How many users hold this role","description":"The blast radius of a role edit, as one number.\n\nExists so the confirmation dialog can say WHO it affects instead of \"all\nholders\". The frontend cannot compute this: the only role-assignment field it\nreceives is `Z_Users.idrole` (8 rows on the test clone), while the real answer\ncomes mostly from `Z_UserRoles` (210) — counting client-side would understate\na 142-user role as 1 and make the warning worse than useless.","operationId":"get_role_holder_count_api_roles__role_id__holders_get","parameters":[{"name":"role_id","in":"path","required":true,"schema":{"type":"integer","title":"Role Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roles/{role_id}/permissions/{permission_id}":{"delete":{"tags":["Permissions"],"summary":"Remove permission from role","description":"Remove a permission from a role.","operationId":"remove_role_permission_api_roles__role_id__permissions__permission_id__delete","parameters":[{"name":"role_id","in":"path","required":true,"schema":{"type":"integer","title":"Role Id"}},{"name":"permission_id","in":"path","required":true,"schema":{"type":"integer","title":"Permission Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user-permissions":{"get":{"tags":["Permissions"],"summary":"List all user-permission mappings","description":"Get all user-permission mappings, optionally filtered by user.","operationId":"list_user_permissions_api_user_permissions_get","parameters":[{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by user ID","title":"User Id"},"description":"Filter by user ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/{user_id}/permissions":{"get":{"tags":["Permissions"],"summary":"Get permissions for a user","description":"Get all user-level permissions assigned to a specific user.","operationId":"get_user_permissions_api_users__user_id__permissions_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Permissions"],"summary":"Add permission to user","description":"Add a single user-level permission to a user.\n\nPrivileged-grant policy (2026-08-13, see `app/db/permissions.py`): the guard\nmoved from \"refuse every `NEVER_ASSIGNABLE` name\" to the same split\n`app/db/admin.py` already applies to roles — `system_admin` refused outright,\n`admin`/`view_all_pvs` allowed with an EXPLICIT `grant_privileged_role` and\naudited in the write's own transaction. The check itself runs in the DB layer,\ninside that transaction: doing it up here would leave a check-then-write race.","operationId":"add_user_permission_api_users__user_id__permissions_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionAssign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Permissions"],"summary":"Set all permissions for a user","description":"Replace all user-level permissions for a user with the given list.\n\nThis is the console's \"Gerir Permissões\" save, and it is a SET-REPLACE that\nre-submits everything the user already holds. That is why the bar is on the\nDELTA (`app/db/permissions.py`): under the old per-id refusal, a user who\nalready carried `admin` could never be saved again — every save re-sent that\nid and every save was 403'd, including saves that only added an ordinary\npermission.","operationId":"set_user_permissions_api_users__user_id__permissions_put","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionsBulkAssign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/{user_id}/permissions/{permission_id}":{"delete":{"tags":["Permissions"],"summary":"Remove permission from user","description":"Remove a user-level permission from a user.","operationId":"remove_user_permission_api_users__user_id__permissions__permission_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"permission_id","in":"path","required":true,"schema":{"type":"integer","title":"Permission Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/role-permissions":{"get":{"tags":["Permissions"],"summary":"List all role-permission mappings","description":"Get all role-permission mappings, optionally filtered by role.","operationId":"list_all_role_permissions_api_role_permissions_get","parameters":[{"name":"role_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by role ID","title":"Role Id"},"description":"Filter by role ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/{user_id}/pv-roles":{"get":{"tags":["Permissions"],"summary":"List PV role assignments for a user","description":"Get all PV role assignments for a specific user.","operationId":"list_user_pv_roles_api_users__user_id__pv_roles_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Permissions"],"summary":"Add or update a PV role for a user","description":"Assign a role to a user at a specific PV. Replaces any existing role at that PV.","operationId":"set_user_pv_role_api_users__user_id__pv_roles_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PvRoleAssign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Permissions"],"summary":"Bulk set PV roles for a user","description":"Replace all PV role assignments for a user within the company.","operationId":"bulk_set_user_pv_roles_api_users__user_id__pv_roles_put","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PvRolesBulkAssign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/{user_id}/pv-roles/{pv_id}":{"delete":{"tags":["Permissions"],"summary":"Remove a user's PV role","description":"Remove a user's role assignment at a specific PV.","operationId":"remove_user_pv_role_api_users__user_id__pv_roles__pv_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pv-roles":{"get":{"tags":["Permissions"],"summary":"List all PV role assignments for the company","description":"Get all PV role assignments for the authenticated user's company.","operationId":"list_company_pv_roles_api_pv_roles_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin-permissions/users/{user_id}":{"get":{"tags":["Permissions"],"summary":"Get a user's individual permissions (admin view)","description":"Get all user-level permissions for a user (admin-accessible).","operationId":"admin_get_user_permissions_api_admin_permissions_users__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Permissions"],"summary":"Add an individual permission to a user","description":"Add a single permission to a user. Blocks system_admin.","operationId":"admin_add_user_permission_api_admin_permissions_users__user_id__post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionAssign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Permissions"],"summary":"Bulk set individual permissions for a user","description":"Replace all user-level permissions. Blocks system_admin.","operationId":"admin_set_user_permissions_api_admin_permissions_users__user_id__put","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionsBulkAssign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin-permissions/users/{user_id}/{permission_id}":{"delete":{"tags":["Permissions"],"summary":"Remove an individual permission from a user","description":"Remove a permission from a user. Blocks removing system_admin.","operationId":"admin_remove_user_permission_api_admin_permissions_users__user_id___permission_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"permission_id","in":"path","required":true,"schema":{"type":"integer","title":"Permission Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company-roles":{"get":{"tags":["Company Roles"],"summary":"List this company's roles","operationId":"list_company_roles_api_company_roles_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Company Roles"],"summary":"Create a role","operationId":"create_company_role_api_company_roles_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleUpsert"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company-roles/assignments":{"get":{"tags":["Company Roles"],"summary":"Every colleague with their roles + modules","description":"The roster behind the \"Atribuir\" screen — one call, never one per user.\n\nReusing an existing endpoint was not possible: `GET /api/users` returns no\nrole or module data and is gated on `modulo.utilizadores` (this screen is\n`modulo.configuracoes`, so an admin holding only Configurações would lose it),\n`GET /company-roles` returns `holders` as a COUNT rather than a roster, and\n`GET /company-roles/users/{id}` is the per-user read this exists to replace.\n\n⚠️ **Privacy note (deliberate widening, flagged in review):** this exposes the\nstaff roster — names and emails — on a `modulo.configuracoes` route, where\ntoday the same list needs `modulo.utilizadores`. It is `admin`-gated and\ntenant-scoped, and an admin can already reach the same names through\n`GET /company-roles` holders, but it is a genuine widening of who sees it.","operationId":"list_role_assignments_api_company_roles_assignments_get","parameters":[{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company-roles/catalog":{"get":{"tags":["Company Roles"],"summary":"The module vocabulary for the editor","description":"Every module a company role may contain, with its pt-PT label AND the\nrules needed to predict what granting it will actually do.\n\nPure vocabulary, so the derivation lives in `app/permissions/modules.py`\nbeside the constants and the gate that reads them — this handler is the HTTP\nhalf and nothing else (house rule). See `modules.module_catalog` for why the\nimplication rules are on the wire rather than re-declared in JavaScript.\n\n    [{\"key\": \"modulo.avaliador\", \"label\": \"Avaliador de Viaturas\",\n      \"ungateable\": false, \"implies\": [\"modulo.viaturas\"], \"implied_by\": []},\n     {\"key\": \"modulo.viaturas\",  \"label\": \"Viaturas\",\n      \"ungateable\": false, \"implies\": [], \"implied_by\": [\"modulo.avaliador\"]},\n     {\"key\": \"modulo.suporte\",   \"label\": \"Suporte\",\n      \"ungateable\": true,  \"implies\": [], \"implied_by\": []},\n     ...]","operationId":"get_module_catalog_api_company_roles_catalog_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company-roles/{idrole}/modules":{"put":{"tags":["Company Roles"],"summary":"Set a role's modules","operationId":"set_role_modules_api_company_roles__idrole__modules_put","parameters":[{"name":"idrole","in":"path","required":true,"schema":{"type":"integer","title":"Idrole"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleModules"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company-roles/{idrole}/reset-template":{"post":{"tags":["Company Roles"],"summary":"Restore a role to its template","operationId":"reset_to_template_api_company_roles__idrole__reset_template_post","parameters":[{"name":"idrole","in":"path","required":true,"schema":{"type":"integer","title":"Idrole"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company-roles/{idrole}":{"delete":{"tags":["Company Roles"],"summary":"Delete a role","operationId":"delete_company_role_api_company_roles__idrole__delete","parameters":[{"name":"idrole","in":"path","required":true,"schema":{"type":"integer","title":"Idrole"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company-roles/users/{utilizador_id}":{"get":{"tags":["Company Roles"],"summary":"A user's roles + effective modules","operationId":"get_user_roles_api_company_roles_users__utilizador_id__get","parameters":[{"name":"utilizador_id","in":"path","required":true,"schema":{"type":"integer","title":"Utilizador Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Company Roles"],"summary":"Replace a user's roles","operationId":"set_user_roles_api_company_roles_users__utilizador_id__put","parameters":[{"name":"utilizador_id","in":"path","required":true,"schema":{"type":"integer","title":"Utilizador Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRolesAssign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/numbers/available":{"get":{"tags":["Call Tracking"],"summary":"Search available phone numbers","description":"Search for available phone numbers to purchase.\nReturns numbers with pricing information.","operationId":"search_numbers_api_call_tracking_numbers_available_get","parameters":[{"name":"country","in":"query","required":false,"schema":{"type":"string","description":"Country code (PT, ES, etc.)","default":"PT","title":"Country"},"description":"Country code (PT, ES, etc.)"},{"name":"locality","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"City/region filter","title":"Locality"},"description":"City/region filter"},{"name":"area_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Area code filter (e.g., 256 for Aveiro)","title":"Area Code"},"description":"Area code filter (e.g., 256 for Aveiro)"},{"name":"phone_number_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Number type filter: local, national, toll-free, mobile, shared-cost","title":"Phone Number Type"},"description":"Number type filter: local, national, toll-free, mobile, shared-cost"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"description":"Max results","default":10,"title":"Limit"},"description":"Max results"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Search Numbers Api Call Tracking Numbers Available Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/numbers/reserve":{"post":{"tags":["Call Tracking"],"summary":"Reserve numbers to close the search-vs-order race","description":"Reserve a list of phone numbers via Telnyx so the user has a window to\nconfirm purchase without losing them to other Telnyx customers.\n\nTelnyx's available_phone_numbers index is non-authoritative — numbers can\nbe listed there yet rejected at order time. This endpoint calls\nPOST /v2/number_reservations to hold the numbers for ~60s (extendable\nonce), making the subsequent purchase deterministic.\n\nBody: {\"phone_numbers\": [\"+351...\", \"+351...\"]}\n\nReturns:\n    {\n        \"reservation_id\": str,\n        \"status\": \"pending\"|\"success\"|\"failure\",\n        \"expires_at\": ISO timestamp,\n        \"phone_numbers\": [\n            {\"phone_number\": \"+351...\", \"status\": \"success\"|\"failure\"},\n            ...\n        ]\n    }\n\nNumbers with status=\"failure\" should be excluded from the upcoming order\nand the user prompted to pick replacements.","operationId":"reserve_tracking_numbers_api_call_tracking_numbers_reserve_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reserve Tracking Numbers Api Call Tracking Numbers Reserve Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/numbers/reservations/{reservation_id}/extend":{"post":{"tags":["Call Tracking"],"summary":"Extend an active reservation by another window","description":"Extend a Telnyx number reservation. Telnyx allows one extension per\nreservation. After that, a fresh reservation must be created (i.e. the\nfrontend should send the user back to the selection step).","operationId":"extend_tracking_reservation_api_call_tracking_numbers_reservations__reservation_id__extend_post","parameters":[{"name":"reservation_id","in":"path","required":true,"schema":{"type":"string","description":"Telnyx reservation ID","title":"Reservation Id"},"description":"Telnyx reservation ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Extend Tracking Reservation Api Call Tracking Numbers Reservations  Reservation Id  Extend Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/requirement-status":{"get":{"tags":["Call Tracking"],"summary":"Preflight: which PT number types can be purchased right now","description":"Returns the current Telnyx requirement-group status for each PT number type.\nUsed by the purchase dialog to disable types whose group isn't 'approved'\nso users see the situation upfront instead of failing at checkout.\n\nCached in Redis for 10 minutes (status changes are rare; admin fix\npropagates within that window).\n\nResponse shape:\n    {\n        \"local\":    {\"status\": \"approved\", \"can_purchase\": true,  \"group_id\": \"...\"},\n        \"national\": {\"status\": \"expired\",  \"can_purchase\": false, \"group_id\": \"...\"}\n    }","operationId":"get_requirement_status_api_call_tracking_requirement_status_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Requirement Status Api Call Tracking Requirement Status Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/price":{"get":{"tags":["Call Tracking"],"summary":"Monthly price of a tracking number for the current company","description":"Per-company monthly price (in cents) for a call-tracking number.\n\nSource of truth = the company's plan pricing. ``0`` means this company's\nplan includes phone rental at no cost (free) — it is NOT a fixed €5. The\npurchase dialog must read this instead of assuming a price.","operationId":"get_tracking_number_price_api_call_tracking_price_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Tracking Number Price Api Call Tracking Price Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/number-requests":{"post":{"tags":["Call Tracking"],"summary":"Request tracking numbers (creates a reservation ticket — no purchase, no billing)","description":"Create a tracking-number reservation request.\n\nBody: {\"entries\": [{\"source\": \"website\", \"team_id\": 3, \"idpointofsale\": 7}, ...]}\n— one entry per desired number (1..20).\n\nOpens ONE ticket (category 'pedido_numeros', visible to the company in\n/tickets) plus one Z_TicketTrackingRequests row per entry, and notifies the\nsystem admins. Deliberately touches neither Telnyx nor billing: no\nZ_TrackingNumbers stub, no credit deduction, no Z_MonthlyUsage row — those\nhappen only at admin attribution time.","operationId":"create_number_request_api_call_tracking_number_requests_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Number Request Api Call Tracking Number Requests Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/number-requests/pending":{"get":{"tags":["Call Tracking"],"summary":"Pending tracking-number reservation summary (banner + dialog warning)","description":"Pending reservation summary: {\"requested_numbers\": X, \"open_tickets\": N}.\n\nrequested_numbers is fulfillment-aware — per portal, entries on open\nreservation tickets minus active numbers of that portal attributed since\nthe first open request — so the banner clears when the requested portals\nactually have numbers, without waiting for the admin to resolve the ticket.\nresolved/closed tickets never count (cancel path). Zero → banner hides.","operationId":"get_pending_number_requests_api_call_tracking_number_requests_pending_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Pending Number Requests Api Call Tracking Number Requests Pending Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/numbers":{"post":{"tags":["Call Tracking"],"summary":"Purchase and create a tracking number","description":"Purchase a phone number from Telnyx and create a tracking number.\n\nRequired fields:\n- phone_number: The phone number to purchase (E.164 format)\n- source: Lead source label (e.g., \"standvirtual\", \"website\")\n- team_id: Team ID - calls will ring team members (required)\n\nOptional fields:\n- idpointofsale: Point of sale ID for billing (defaults to user's PV or team's PV)\n\nStatus codes:\n- 201: Number purchased and active.\n- 202: Order accepted but still pending at Telnyx; a webhook will finalise later.\n       Response shape: {status: \"pending\", order_id, phone_number}. No credits\n       are deducted yet — the webhook handler charges on success.\n- 409: An active tracking row already exists for this phone_number.\n- 502: Telnyx rejected the order outright.","operationId":"create_number_api_call_tracking_numbers_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Number Api Call Tracking Numbers Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Call Tracking"],"summary":"List tracking numbers","description":"List all tracking numbers for the company.","operationId":"list_numbers_api_call_tracking_numbers_get","parameters":[{"name":"active_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only show active numbers","default":true,"title":"Active Only"},"description":"Only show active numbers"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Numbers Api Call Tracking Numbers Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/numbers/bulk":{"post":{"tags":["Call Tracking"],"summary":"Purchase and create multiple tracking numbers","description":"Purchase multiple phone numbers from Telnyx and create tracking numbers.\n\nRequired fields:\n- phone_numbers: List of E.164 phone numbers\n- source: Lead source label\n- team_id: Team ID\n\nOptional fields:\n- idpointofsale: Point of sale ID for billing\n\nReturns:\n    {\n      \"succeeded\": [<tracking_row>, ...],\n      \"failed\":    [{phone_number, reason}, ...],\n      \"pending\":   [{phone_number, order_id, tracking_id}, ...]\n    }\n\nErrors out with 400 before touching Telnyx if the input list contains\nduplicates or if any of the requested numbers is already owned.","operationId":"create_numbers_bulk_api_call_tracking_numbers_bulk_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Numbers Bulk Api Call Tracking Numbers Bulk Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/numbers/{number_id}":{"get":{"tags":["Call Tracking"],"summary":"Get tracking number details","description":"Get details of a specific tracking number.","operationId":"get_number_api_call_tracking_numbers__number_id__get","parameters":[{"name":"number_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Number Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Number Api Call Tracking Numbers  Number Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Call Tracking"],"summary":"Update tracking number","description":"Update a tracking number's configuration.\n\nUpdatable fields:\n- source: Lead source label\n- team_id: Team ID for call routing (required, cannot be null)\n- idpointofsale: Point of sale ID (also syncs Z_MonthlyUsage billing)\n- active: Enable/disable the number","operationId":"update_number_api_call_tracking_numbers__number_id__patch","parameters":[{"name":"number_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Number Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Number Api Call Tracking Numbers  Number Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Call Tracking"],"summary":"Delete tracking number","description":"Deactivate a tracking number.\nOptionally release it from Telnyx (cannot be undone).","operationId":"delete_number_api_call_tracking_numbers__number_id__delete","parameters":[{"name":"number_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Number Id"}},{"name":"release_from_telnyx","in":"query","required":false,"schema":{"type":"boolean","description":"Also release from Telnyx","default":false,"title":"Release From Telnyx"},"description":"Also release from Telnyx"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/calls":{"get":{"tags":["Call Tracking"],"summary":"List calls","description":"List call logs for the company.","operationId":"list_call_logs_api_call_tracking_calls_get","parameters":[{"name":"tracking_number_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by tracking number","title":"Tracking Number Id"},"description":"Filter by tracking number"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by status","title":"Status"},"description":"Filter by status"},{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Filter by team(s) — repeat param for multiple","title":"Team Id"},"description":"Filter by team(s) — repeat param for multiple"},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by Utilizadores.ID (calls answered by or analyzed for this user)","title":"User Id"},"description":"Filter by Utilizadores.ID (calls answered by or analyzed for this user)"},{"name":"analyzed_only","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"True = only analyzed, False = only not analyzed, None = all","title":"Analyzed Only"},"description":"True = only analyzed, False = only not analyzed, None = all"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"description":"Max results","default":100,"title":"Limit"},"description":"Max results"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Offset for pagination","default":0,"title":"Offset"},"description":"Offset for pagination"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Call Logs Api Call Tracking Calls Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/calls/{call_id}":{"get":{"tags":["Call Tracking"],"summary":"Get call details","description":"Get details of a specific call.","operationId":"get_call_api_call_tracking_calls__call_id__get","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Call Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Call Api Call Tracking Calls  Call Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/calls/{call_id}/link-lead":{"post":{"tags":["Call Tracking"],"summary":"Link call to lead","description":"Link a call to a lead record.\n\nRequired fields:\n- lead_id: The lead ID to link","operationId":"link_to_lead_api_call_tracking_calls__call_id__link_lead_post","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Call Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Link To Lead Api Call Tracking Calls  Call Id  Link Lead Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/stats":{"get":{"tags":["Call Tracking"],"summary":"Get call statistics","description":"Unified call statistics: totals, by_team, by_user, by_source, by_date.\nFilter by one or more team_ids: ?team_id=1&team_id=15&team_id=16","operationId":"get_stats_api_call_tracking_stats_get","parameters":[{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Filter by team(s) — repeat param for multiple","title":"Team Id"},"description":"Filter by team(s) — repeat param for multiple"},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"description":"Number of days to include","default":30,"title":"Days"},"description":"Number of days to include"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Stats Api Call Tracking Stats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-tracking/calls/{call_id}/recording":{"get":{"tags":["Call Tracking"],"summary":"Get call recording presigned URL","description":"Get a presigned URL to access the call recording.\n\nThe URL expires after the specified time (default 1 hour).\nUse this endpoint to stream/download recordings securely.","operationId":"get_call_recording_api_call_tracking_calls__call_id__recording_get","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Call Id"}},{"name":"expires_in","in":"query","required":false,"schema":{"type":"integer","maximum":86400,"minimum":60,"description":"URL expiration in seconds (default 1 hour, max 24 hours)","default":3600,"title":"Expires In"},"description":"URL expiration in seconds (default 1 hour, max 24 hours)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Call Recording Api Call Tracking Calls  Call Id  Recording Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/check/{pv_id}":{"post":{"tags":["SCUTS"],"summary":"Trigger Scuts Check","description":"Manually trigger SCUTS check for a specific PV.\nRuns as a detached async task - does not block worker.\n\nRequires the PV to belong to the authenticated user's company.\n\nArgs:\n    pv_id: Point of sale ID to check\n    send_email: Whether to send email alert (default True)\n\nReturns immediately with status 'started'.","operationId":"trigger_scuts_check_api_scuts_check__pv_id__post","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"send_email","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Send Email"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/history":{"get":{"tags":["SCUTS"],"summary":"Get Scuts History","description":"Get recent SCUTS check history aggregated across one or more PVs.\n\nArgs:\n    pv_ids: One or more point-of-sale IDs (repeat the param: ?pv_ids=1&pv_ids=2)\n    days: Number of days to look back (default 7)","operationId":"get_scuts_history_api_scuts_history_get","parameters":[{"name":"pv_ids","in":"query","required":true,"schema":{"type":"array","items":{"type":"integer"},"title":"Pv Ids"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":7,"title":"Days"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/summary":{"get":{"tags":["SCUTS"],"summary":"Get Scuts Summary","description":"Get summary of unpaid SCUTS aggregated across one or more PVs from the last check.","operationId":"get_scuts_summary_api_scuts_summary_get","parameters":[{"name":"pv_ids","in":"query","required":true,"schema":{"type":"array","items":{"type":"integer"},"title":"Pv Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/dashboard":{"get":{"tags":["SCUTS"],"summary":"Get Scuts Dashboard","description":"Get SCUTS dashboard data aggregated across one or more PVs.\n\nReturns the current status (latest check per plate per PV) plus period\nand all-time stats summed across the selected PVs. The savings/detections\nfigures remain company-wide (lifetime), independent of selection.","operationId":"get_scuts_dashboard_api_scuts_dashboard_get","parameters":[{"name":"pv_ids","in":"query","required":true,"schema":{"type":"array","items":{"type":"integer"},"title":"Pv Ids"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":7,"title":"Days"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/unpaid":{"get":{"tags":["SCUTS"],"summary":"Get Current Unpaid","description":"Get list of plates with CURRENT unpaid tolls aggregated across one or more PVs.\n\nReturns unique (PV, matricula) pairs only - each appears once with its most\nrecent status. Plates are sorted by amount (highest first).","operationId":"get_current_unpaid_api_scuts_unpaid_get","parameters":[{"name":"pv_ids","in":"query","required":true,"schema":{"type":"array","items":{"type":"integer"},"title":"Pv Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/debug/{plate}":{"get":{"tags":["SCUTS"],"summary":"Debug Single Plate","description":"DEBUG: Check a single plate via CTT's internal JSON API and return a\nconsolidated diagnostic payload (HTTP status, version tokens in use,\nversion-mismatch flag, parsed result, raw response).\nRequires plate ownership (vehicle must belong to user's company) or system_admin role.\n\nExample: GET /api/scuts/debug/AA-00-BB","operationId":"debug_single_plate_api_scuts_debug__plate__get","parameters":[{"name":"plate","in":"path","required":true,"schema":{"type":"string","title":"Plate"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/debug/{plate}/html":{"get":{"tags":["SCUTS"],"summary":"Debug Single Plate Html","description":"DEBUG: Return a formatted HTML view of the check result.\nRequires plate ownership (vehicle must belong to user's company) or system_admin role.","operationId":"debug_single_plate_html_api_scuts_debug__plate__html_get","parameters":[{"name":"plate","in":"path","required":true,"schema":{"type":"string","title":"Plate"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/debug/{plate}/raw":{"get":{"tags":["SCUTS"],"summary":"Debug Single Plate Raw","description":"DEBUG: Return the RAW API response from CTT for inspection.\nShows all cookies, headers, and the full JSON response.\nRequires plate ownership (vehicle must belong to user's company) or system_admin role.\n\nExample: GET /api/scuts/debug/33-OF-30/raw","operationId":"debug_single_plate_raw_api_scuts_debug__plate__raw_get","parameters":[{"name":"plate","in":"path","required":true,"schema":{"type":"string","title":"Plate"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/versions":{"get":{"tags":["SCUTS"],"summary":"Get Ctt Versions","description":"DEBUG: the CTT version tokens currently in use and their source\n('redis' hot-store from auto-recovery, or 'settings' .env seed). System-admin only.","operationId":"get_ctt_versions_api_scuts_versions_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/rediscover":{"post":{"tags":["SCUTS"],"summary":"Rediscover Ctt Versions","description":"DEBUG: force a CTT token re-discovery now (bypasses the auto-recovery rate\nlimit) and hot-swap if the discovered tokens differ. System-admin only.\nReturns {old, discovered, swapped, reason, source}.","operationId":"rediscover_ctt_versions_api_scuts_rediscover_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-alerts/iuc":{"get":{"tags":["Vehicle Alerts"],"summary":"Iuc Alerts","description":"Vehicles needing IUC attention (repeat ?pv_ids=1&pv_ids=2).\n\nCovers four bands: `vencido` (imported, 1st-IUC deadline missed), `alta`\n(due this month), `media` (next month) and `sem_informacao` (no usable\nregistration date). Vehicles with nothing due soon are omitted, as are\n100%-electric ones — they are exempt from IUC in Portugal (hybrids are not).","operationId":"iuc_alerts_api_vehicle_alerts_iuc_get","parameters":[{"name":"pv_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Pv Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-alerts/iuc/{vehicle_id}/paid":{"post":{"tags":["Vehicle Alerts"],"summary":"Mark Iuc Paid Endpoint","description":"Mark a vehicle's IUC as regularised, silencing its alert everywhere.\n\nBody `{year, month}` is the obligation the alert shows — for a `vencido` row\nthat is `first_due_year`/`first_due_month`, otherwise `due_year`/`due_month`\n(the FE already has all four). Company-scoped from the JWT.\n\nThis ONLY silences the alert. Booking the IUC cost is a separate, optional step\nthe FE drives through the existing \"Adicionar Saída › Custos Viatura\" dialog\n(AddMovementDialog), pre-filled with the IUC rubrica + this vehicle — so the\nfull movement flow (fornecedor, conta, fatura, pagamento) is reused instead of\na stripped-down one here.","operationId":"mark_iuc_paid_endpoint_api_vehicle_alerts_iuc__vehicle_id__paid_post","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Vehicle Alerts"],"summary":"Unmark Iuc Paid Endpoint","description":"Clear a vehicle's regularised-IUC mark (re-arms the alert).","operationId":"unmark_iuc_paid_endpoint_api_vehicle_alerts_iuc__vehicle_id__paid_delete","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-alerts/iuc/{vehicle_id}/status":{"get":{"tags":["Vehicle Alerts"],"summary":"Iuc Status Endpoint","description":"Current IUC obligation + regularised mark for one vehicle (the vehicle ficha\nreads this to show status + the 'Marcar IUC pago' action).","operationId":"iuc_status_endpoint_api_vehicle_alerts_iuc__vehicle_id__status_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-alerts/inspection":{"get":{"tags":["Vehicle Alerts"],"summary":"Inspection Alerts","description":"Vehicles with inspection overdue / expiring (≤2 months).","operationId":"inspection_alerts_api_vehicle_alerts_inspection_get","parameters":[{"name":"pv_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Pv Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-alerts/stock-stalled":{"get":{"tags":["Vehicle Alerts"],"summary":"Stock Stalled Alerts","description":"In-stock vehicles stalled >= 60 days (capital parado).","operationId":"stock_stalled_alerts_api_vehicle_alerts_stock_stalled_get","parameters":[{"name":"pv_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Pv Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-alerts/car-no-leads":{"get":{"tags":["Vehicle Alerts"],"summary":"Car No Leads Alerts","description":"In-stock vehicles with no lead in the last 90 days (sem procura).","operationId":"car_no_leads_alerts_api_vehicle_alerts_car_no_leads_get","parameters":[{"name":"pv_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Pv Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-alerts/listing-quality":{"get":{"tags":["Vehicle Alerts"],"summary":"Listing Quality Alerts","description":"In-stock listings with fewer than 8 photos (anúncios a melhorar).","operationId":"listing_quality_alerts_api_vehicle_alerts_listing_quality_get","parameters":[{"name":"pv_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Pv Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vehicle-alerts/por-fechar":{"get":{"tags":["Vehicle Alerts"],"summary":"Por Fechar Alerts","description":"Sold vehicles still open financially (viaturas vendidas por fechar).\n\n`data_contrato` and `dias` refer to the contract, not the sale, and are null\nfor a vehicle marked sold without any contract.","operationId":"por_fechar_alerts_api_vehicle_alerts_por_fechar_get","parameters":[{"name":"pv_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Pv Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/audit-logs":{"get":{"tags":["Audit Logs"],"summary":"Listar registos de auditoria","description":"Listar registos de auditoria da empresa.\n\nRetorna os registos de ações (criação, edição, eliminação) ordenados por data.","operationId":"list_audit_logs_api_audit_logs_get","parameters":[{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filtrar por utilizador","title":"User Id"},"description":"Filtrar por utilizador"},{"name":"user_pv_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filtrar por ponto de venda","title":"User Pv Id"},"description":"Filtrar por ponto de venda"},{"name":"endpoint","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrar por endpoint","title":"Endpoint"},"description":"Filtrar por endpoint"},{"name":"method","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrar por método (POST, PUT, PATCH, DELETE)","title":"Method"},"description":"Filtrar por método (POST, PUT, PATCH, DELETE)"},{"name":"response_status","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filtrar por código de resposta","title":"Response Status"},"description":"Filtrar por código de resposta"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"description":"Máximo de registos","default":100,"title":"Limit"},"description":"Máximo de registos"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Registos a saltar (paginação)","default":0,"title":"Offset"},"description":"Registos a saltar (paginação)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/audit-logs/{log_id}":{"get":{"tags":["Audit Logs"],"summary":"Obter registo de auditoria","description":"Obter um registo de auditoria por ID.","operationId":"get_audit_log_api_audit_logs__log_id__get","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"integer","title":"Log Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/logs/{module}":{"get":{"tags":["Audit Logs"],"summary":"Histórico de ações do módulo","description":"Obter histórico de ações de um módulo específico.\n\nExemplo: /api/logs/leads, /api/logs/vehicles","operationId":"get_module_history_api_logs__module__get","parameters":[{"name":"module","in":"path","required":true,"schema":{"type":"string","title":"Module"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"method","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrar por método (POST, PUT, PATCH, DELETE)","title":"Method"},"description":"Filtrar por método (POST, PUT, PATCH, DELETE)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/preview":{"post":{"tags":["Declarations"],"summary":"Preview Declaration","description":"Render a declaration as HTML for frontend preview.\n\nBody:\n    template_id: int — Z_DeclarationTemplates.id\n    subject_id: int — Record ID (vehicle, contract, or client)\n    client_id: int (optional) — Client/supplier ID (auto-detected for vehicles)\n    website_id: int (optional) — Website ID for theme colors (auto-detected if not sent)\n\nReturns:\n    rendered_html: str — Full HTML with resolved placeholders, Tailwind CSS, header\n    context: dict — Raw placeholder data\n    template: dict — Template metadata (id, name, id_modulo, tipo_doc)","operationId":"preview_declaration_api_declarations_preview_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/preview-batch":{"post":{"tags":["Declarations"],"summary":"Preview Declarations Batch","description":"Render multiple declaration previews at once.\n\nBody:\n    template_ids: list[int] — List of Z_DeclarationTemplates.id\n    subject_id: int — Record ID (vehicle, contract, or client)\n    client_id: int (optional) — Client/supplier ID\n    website_id: int (optional) — Website ID for theme colors","operationId":"preview_declarations_batch_api_declarations_preview_batch_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/generate":{"post":{"tags":["Declarations"],"summary":"Generate Declaration","description":"Generate a single declaration PDF.\n\nBody:\n    template_id: int — Z_DeclarationTemplates.id\n    subject_id: int — Record ID (vehicle, contract, or client)\n    client_id: int (optional) — Client/supplier ID (auto-detected for vehicles)\n    website_id: int (optional) — Website ID for theme colors","operationId":"generate_declaration_api_declarations_generate_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/generate-batch":{"post":{"tags":["Declarations"],"summary":"Generate Declarations Batch","description":"Generate multiple declaration PDFs at once.\n\nBody:\n    template_ids: list[int] — List of Z_DeclarationTemplates.id to generate\n    subject_id: int — Record ID (vehicle, contract, or client)\n    client_id: int (optional) — Client/supplier ID (auto-detected for vehicles)\n    website_id: int (optional) — Website ID for theme colors\n    trigger_action: str (optional) — \"on_reservation\" or \"on_sale\" to update vehicle estado","operationId":"generate_declarations_batch_api_declarations_generate_batch_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/templates":{"get":{"tags":["Declarations"],"summary":"List Available Templates","description":"List available declaration templates for the user's company.\n\nReturns system defaults + company-specific overrides.","operationId":"list_available_templates_api_declarations_templates_get","parameters":[{"name":"id_modulo","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by module (11=Viaturas, 5=Contratos, 12=Clientes)","title":"Id Modulo"},"description":"Filter by module (11=Viaturas, 5=Contratos, 12=Clientes)"},{"name":"trigger_action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by trigger action (on_purchase, on_sale, etc.)","title":"Trigger Action"},"description":"Filter by trigger action (on_purchase, on_sale, etc.)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/fua-generate":{"post":{"tags":["Declarations"],"summary":"Fua Generate","description":"Resolve FUA template placeholders against live database data.\n\nReplacement for the legacy Flask FUA service. Queries FuaTemplates2 +\nTipoDecFua, resolves [Placeholder] markers with actual entity values,\nand returns the resolved field texts as JSON.\n\nBody:\n    tipodec: int — TipoDeclaracao.ID (declaration type)\n    subject_array: list — [{table_name: str, subject_id: int}, ...]\n\nReturns:\n    {message: str, Placeholders: [{ID, Descricao, Texto}, ...]}","operationId":"fua_generate_api_declarations_fua_generate_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/dua-generate":{"post":{"tags":["Declarations"],"summary":"Dua Generate","description":"Generate a DUA (Declaração Única Automóvel) PDF document.\n\nFills a DUA PDF template with buyer/seller data, vehicle info,\nbanking details, and current date. Creates a Registos record\nand uploads the filled PDF to S3.\n\nPARTIAL GENERATION: all four ids are OPTIONAL. The user fills whatever part of\nthe dossier they have and the rest of the official form is left blank, exactly\nas a human hand-filling it would. An id that IS supplied must still resolve\ninside the caller's company — an unresolvable id is a 400, never a blank field.\n\nBody (all optional):\n    sujeito_ativo_id: int — Buyer client ID\n    sujeito_passivo_id: int — Seller client ID\n    vehicle_id: int — Vehicle ID\n    restituicao_pv_id: int — PV ID for banking/restitution data\n\nReturns:\n    {status, registo_id, document_id, s3_url, pdf_url, is_partial, message}","operationId":"dua_generate_api_declarations_dua_generate_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/dua-readiness":{"get":{"tags":["Declarations"],"summary":"Dua Readiness","description":"Per-entity readiness check for DUA generation.\n\nFor each ID provided, returns the hydrated entity data (already shaped\nfor the DUA template) plus a list of required fields that are empty.\nFrontend uses this to drive completeness chips and the \"what's missing\"\nexpandable panel on /dua-declarations.\n\nMulti-tenancy: company_id is taken from the JWT and passed to every DB\nfunction. PV identity hydration is gated behind the banking lookup\n(which enforces IDempresa) so a foreign PV can never leak.","operationId":"dua_readiness_api_declarations_dua_readiness_get","parameters":[{"name":"sujeito_ativo_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sujeito Ativo Id"}},{"name":"sujeito_passivo_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sujeito Passivo Id"}},{"name":"vehicle_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vehicle Id"}},{"name":"restituicao_pv_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Restituicao Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/contract-dua-readiness":{"get":{"tags":["Declarations"],"summary":"Contract Dua Readiness","description":"Per-entity DUA readiness for a sale contract.\n\nResolves the buyer (Contratos.Cliente), seller (the dealership's own client —\nNIF == PV NIPC), vehicle (Contratos.Viatura) and restitution PV (the user's\nPV) from the contract, and reports for each the hydrated data plus the\nrequired fields still empty. The contracts \"Declarações\" modal calls this to\ngate the DUA before generation.\n\nReturns the buyer/seller/vehicle/pv blocks plus `contract_error` and\n`seller_unresolved`. company_id and pv_id come from the JWT.","operationId":"contract_dua_readiness_api_declarations_contract_dua_readiness_get","parameters":[{"name":"contract_id","in":"query","required":true,"schema":{"type":"integer","description":"Contratos.ID","title":"Contract Id"},"description":"Contratos.ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declarations/vehicle-dua-readiness":{"get":{"tags":["Declarations"],"summary":"Vehicle Dua Readiness","description":"Per-entity DUA (Compra) readiness for a purchased vehicle.\n\nResolves the buyer (the dealership — NIF == PV NIPC), seller (the vehicle's\nfornecedor — Viatura.Fornece), vehicle and restitution PV (the user's PV),\nand reports for each the hydrated data plus the required fields still empty.\nThe vehicle \"Declarações\" modal calls this to gate the DUA before generation.\n\nReturns the buyer/seller/vehicle/pv blocks plus `error`. company_id and\npv_id come from the JWT.","operationId":"vehicle_dua_readiness_api_declarations_vehicle_dua_readiness_get","parameters":[{"name":"vehicle_id","in":"query","required":true,"schema":{"type":"integer","description":"Viatura.ID","title":"Vehicle Id"},"description":"Viatura.ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates":{"get":{"tags":["Declaration Templates (Admin)"],"summary":"List Templates","description":"List all templates (system defaults + company overrides).","operationId":"list_templates_api_declaration_templates_get","parameters":[{"name":"id_modulo","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by module","title":"Id Modulo"},"description":"Filter by module"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Declaration Templates (Admin)"],"summary":"Create Template","description":"Create a new template.\n\nBody:\n    name: str (required)\n    id_modulo: int (required)\n    template_type: str (optional, default 'html' — 'html' or 'pdf')\n    design_json: dict (preferred for html — block-based editor output)\n    html_content: str (legacy — required if design_json absent for html type)\n    css_content: str (optional)\n    tipo_doc: int (optional)\n    trigger_action: str (optional)\n    pdf_template_url: str (required for pdf type — S3 URL of fillable PDF)","operationId":"create_template_api_declaration_templates_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/placeholders":{"get":{"tags":["Declaration Templates (Admin)"],"summary":"Get Placeholders","description":"List available placeholder variables grouped by category.","operationId":"get_placeholders_api_declaration_templates_placeholders_get","parameters":[{"name":"id_modulo","in":"query","required":true,"schema":{"type":"integer","description":"Module ID (11=Viaturas, 5=Contratos, 12=Clientes)","title":"Id Modulo"},"description":"Module ID (11=Viaturas, 5=Contratos, 12=Clientes)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/trigger-actions":{"get":{"tags":["Declaration Templates (Admin)"],"summary":"Get Trigger Actions","description":"List available trigger_action values for the dropdown.","operationId":"get_trigger_actions_api_declaration_templates_trigger_actions_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/blocks":{"get":{"tags":["Declaration Templates (Admin)"],"summary":"Get Block Catalog","description":"Return the catalog of block types available in the visual editor.\nFrontend uses this to populate the block palette.","operationId":"get_block_catalog_api_declaration_templates_blocks_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/editor-css":{"get":{"tags":["Declaration Templates (Admin)"],"summary":"Get Editor Css","description":"Return the V5 base CSS so the visual ('Visual') editor for custom_html\nblocks can render the document body styled like the generated PDF. Single\nsource of truth — the same BASE_CSS used by the generation/preview pipeline.","operationId":"get_editor_css_api_declaration_templates_editor_css_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/document-types":{"get":{"tags":["Declaration Templates (Admin)"],"summary":"Get Document Types For Module","description":"List document types (TipoDocsNomeModulo) for the given module — global\ntypes + the caller's own custom types. Used by the tipo_doc dropdown.","operationId":"get_document_types_for_module_api_declaration_templates_document_types_get","parameters":[{"name":"id_modulo","in":"query","required":true,"schema":{"type":"integer","description":"Module ID — returns doc types where TipoDocsNomeModulo.Modulo matches (or is NULL)","title":"Id Modulo"},"description":"Module ID — returns doc types where TipoDocsNomeModulo.Modulo matches (or is NULL)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Declaration Templates (Admin)"],"summary":"Create Document Type","description":"Create a tenant-specific document type (TipoDocsNomeModulo) so the user can\nadd one inline when no existing type matches. The new type is scoped to the\ncaller's company (company_id) and is therefore invisible to other tenants.\n\nDedupe: if a global or own-company type with the same name + module already\nexists, that one is returned instead of creating a duplicate.\n\nBody:\n    name: str (required)\n    id_modulo: int (required) — 5 (Contratos), 11 (Viaturas) or 12 (Clientes)","operationId":"create_document_type_api_declaration_templates_document_types_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/ai-generate":{"post":{"tags":["Declaration Templates (Admin)"],"summary":"Ai Generate Template","description":"Generate declaration template HTML using AI (Claude).\n\nThe AI generates HTML body content using the V5 CSS design system and we\nreturn it as an editable DRAFT (design_json + html_content) — it is NOT\nsaved. The frontend opens it in the editor; the user picks the mandatory\nTipo de Documento and saves via the normal POST /declaration-templates\n(which enforces a valid tipo_doc). This mirrors the import-document flow\nand guarantees no NULL-tipo_doc template is ever persisted.\n\nBody:\n    example_text: str (required, min 10 chars) — description of what the user wants\n    placeholders: list[str] (required, min 1) — placeholder keys to include\n    id_modulo: int (required) — 5, 11, or 12\n    name: str (optional) — template name (defaults to \"Declaração IA\")\n    trigger_action: str (optional) — trigger for auto-generation\n    tipo_doc: int (optional) — document type ID, pre-fills the draft's metadata","operationId":"ai_generate_template_api_declaration_templates_ai_generate_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/import-document":{"post":{"tags":["Declaration Templates (Admin)"],"summary":"Import Document","description":"Convert one or more uploaded .docx/.doc/.pdf/.txt files into our template\nmodel using AI, merging them into a SINGLE editable DRAFT.\n\nReturns a DRAFT (design_json + html_content + unmapped fields) — it is NOT\nsaved. The frontend opens it in the editor; the user reviews and saves via the\nnormal POST /declaration-templates. Conversion is best-effort.\n\nMultipart form:\n    files: one or more .docx/.doc/.pdf/.txt (repeated part; up to MAX_IMPORT_FILES).\n           A single legacy `file` part is also accepted for backward compat.\n    id_modulo: int (required) — 5 (Contratos), 11 (Viaturas) or 12 (Clientes)\n    instructions: optional freeform guidance passed to the AI (not persisted)\n    name / trigger_action / tipo_doc: optional, pre-fill the draft's metadata","operationId":"import_document_api_declaration_templates_import_document_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_document_api_declaration_templates_import_document_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/{template_id}":{"get":{"tags":["Declaration Templates (Admin)"],"summary":"Get Template","description":"Get a single template with full html_content for the editor.","operationId":"get_template_api_declaration_templates__template_id__get","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Declaration Templates (Admin)"],"summary":"Update Template","description":"Update an existing template.\n\nBody (all optional):\n    name, html_content, css_content, id_modulo, tipo_doc, trigger_action,\n    is_active, template_type, pdf_template_url, design_json\n\n    For id_modulo / tipo_doc / trigger_action, sending `null` clears the\n    column; omitting the key leaves it unchanged.","operationId":"update_template_api_declaration_templates__template_id__put","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Declaration Templates (Admin)"],"summary":"Delete Template","description":"Delete a template. Only company overrides can be deleted, not system defaults.","operationId":"delete_template_api_declaration_templates__template_id__delete","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/{template_id}/clone":{"post":{"tags":["Declaration Templates (Admin)"],"summary":"Clone Template","description":"Clone a template (a system default or one of the company's own) into a NEW\ncompany-owned, editable copy. The original is left untouched.\n\nOnly HTML templates can be cloned — PDF form-fill templates (e.g. DUA) use a\ndifferent mechanism and are out of scope.\n\nBody (optional):\n    name: str — name for the copy (defaults to \"Cópia de {original}\")","operationId":"clone_template_api_declaration_templates__template_id__clone_post","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/declaration-templates/preview":{"post":{"tags":["Declaration Templates (Admin)"],"summary":"Preview Template","description":"Render a preview PDF with sample data.\n\nBody:\n    template_type: str (optional, default 'html')\n    design_json: dict (preferred for html — block-based editor output)\n    html_content: str (legacy — required if design_json absent)\n    css_content: str (optional, html only)\n    id_modulo: int (required for html type)\n    pdf_template_url: str (required for pdf type)","operationId":"preview_template_api_declaration_templates_preview_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/warranties":{"get":{"tags":["Warranties"],"summary":"List Warranties","operationId":"list_warranties_api_warranties_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Warranties"],"summary":"Create Warranty","description":"Body:\n    name: str (required)\n    design_json: dict (preferred — block editor output for the text)\n    html_content: str (optional legacy alternative)\n    template_id: int (optional — link an existing template instead)","operationId":"create_warranty_api_warranties_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/warranties/{warranty_id}/clone":{"post":{"tags":["Warranties"],"summary":"Clone Warranty","description":"Clone a warranty (a global/system default or one of the company's own) into a\nNEW company-owned, editable one, copying its linked template's text. The\noriginal is left untouched.\n\nBody (optional):\n    name: str — name for the copy (defaults to \"Cópia de {original}\")","operationId":"clone_warranty_api_warranties__warranty_id__clone_post","parameters":[{"name":"warranty_id","in":"path","required":true,"schema":{"type":"integer","title":"Warranty Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/warranties/{warranty_id}":{"put":{"tags":["Warranties"],"summary":"Update Warranty","description":"Body (all optional): name, design_json, html_content.","operationId":"update_warranty_api_warranties__warranty_id__put","parameters":[{"name":"warranty_id","in":"path","required":true,"schema":{"type":"integer","title":"Warranty Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Warranties"],"summary":"Delete Warranty","operationId":"delete_warranty_api_warranties__warranty_id__delete","parameters":[{"name":"warranty_id","in":"path","required":true,"schema":{"type":"integer","title":"Warranty Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduler/jobs":{"get":{"tags":["Scheduler"],"summary":"Get Scheduled Jobs","description":"List all scheduled jobs with their status and next run times.\nWorks even when scheduler is disabled (shows job configuration).\n\nReturns:\n    Dict with scheduler_running flag and list of jobs","operationId":"get_scheduled_jobs_api_scheduler_jobs_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduler/jobs/{job_id}":{"get":{"tags":["Scheduler"],"summary":"Get Job","description":"Get detailed information about a specific job.\nWorks even when scheduler is disabled (shows job configuration).\n\nArgs:\n    job_id: The job identifier\n\nReturns:\n    Job details including trigger configuration","operationId":"get_job_api_scheduler_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduler/jobs/{job_id}/run":{"post":{"tags":["Scheduler"],"summary":"Run Job Now","description":"Manually trigger a job to run immediately.\nWorks even when scheduler is disabled (for testing).\n\nArgs:\n    job_id: The job identifier\n\nReturns:\n    Job execution result","operationId":"run_job_now_api_scheduler_jobs__job_id__run_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduler/jobs/{job_id}/pause":{"post":{"tags":["Scheduler"],"summary":"Pause Scheduled Job","description":"Pause a scheduled job.\n\nThe job will not run until resumed. Use /jobs/{job_id}/resume to re-enable.\n\nArgs:\n    job_id: The job identifier\n\nReturns:\n    Success message","operationId":"pause_scheduled_job_api_scheduler_jobs__job_id__pause_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduler/jobs/{job_id}/resume":{"post":{"tags":["Scheduler"],"summary":"Resume Scheduled Job","description":"Resume a paused job.\n\nArgs:\n    job_id: The job identifier\n\nReturns:\n    Success message with next run time","operationId":"resume_scheduled_job_api_scheduler_jobs__job_id__resume_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduler/logs":{"get":{"tags":["Scheduler"],"summary":"Get Execution Logs","description":"Get job execution logs.\n\nArgs:\n    job_id: Filter by specific job (optional)\n    status: Filter by status - 'completed' or 'error' (optional)\n    limit: Max records to return (default 50)\n    offset: Pagination offset (default 0)\n\nReturns:\n    List of execution log entries","operationId":"get_execution_logs_api_scheduler_logs_get","parameters":[{"name":"job_id","in":"query","required":false,"schema":{"type":"string","title":"Job Id"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduler/logs/{job_id}":{"get":{"tags":["Scheduler"],"summary":"Get Job Execution Logs","description":"Get execution logs for a specific job.\n\nArgs:\n    job_id: The job identifier\n    limit: Max records to return (default 20)\n\nReturns:\n    List of execution log entries for this job","operationId":"get_job_execution_logs_api_scheduler_logs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduler/stats":{"get":{"tags":["Scheduler"],"summary":"Get Execution Stats","description":"Get execution statistics for all jobs.\n\nArgs:\n    days: Look back period in days (default 30)\n\nReturns:\n    Stats per job including total runs, success rate, avg duration","operationId":"get_execution_stats_api_scheduler_stats_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/plans/current":{"get":{"tags":["Plans"],"summary":"Get company's current plan with terms, services, and active subscriptions","description":"Get the authenticated company's current plan, pricing, service terms,\nand active subscriptions.\n\nReturns:\n- plan: Plan info (id, name, subscribed_at)\n- services: List of services with pricing and terms for this plan\n- subscriptions: Active subscriptions from Z_MonthlyUsage grouped by service\n- totals: Monthly cost summary","operationId":"get_current_plan_api_plans_current_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Current Plan Api Plans Current Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/subscribe":{"post":{"tags":["SCUTS Subscription"],"summary":"Subscribe PVs to SCUTS monitoring","description":"Subscribe one or more PVs to SCUTS monitoring.\n\nCharges immediately for each PV and creates monthly usage entries.\n\nRequest body:\n- pv_ids: List of PV IDs to subscribe\n\nReturns:\n- subscribed: List of successfully subscribed PVs\n- failed: List of PVs that failed to subscribe\n- already_subscribed: List of PVs already subscribed","operationId":"subscribe_to_scuts_api_scuts_subscribe_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Subscribe To Scuts Api Scuts Subscribe Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/unsubscribe/{pv_id}":{"delete":{"tags":["SCUTS Subscription"],"summary":"Unsubscribe PV from SCUTS monitoring","description":"Unsubscribe a PV from SCUTS monitoring.\n\nArgs:\n    pv_id: The PV ID to unsubscribe","operationId":"unsubscribe_from_scuts_api_scuts_unsubscribe__pv_id__delete","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unsubscribe From Scuts Api Scuts Unsubscribe  Pv Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scuts/subscriptions":{"get":{"tags":["SCUTS Subscription"],"summary":"List active SCUTS subscriptions","description":"List all active SCUTS subscriptions for the company.\n\nReturns list of PVs subscribed to SCUTS with subscription details.","operationId":"list_scuts_subscriptions_api_scuts_subscriptions_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Scuts Subscriptions Api Scuts Subscriptions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/phone/subscribe":{"post":{"tags":["Phone Subscription"],"summary":"Subscribe to phone numbers (purchase tracking numbers)","description":"Subscribe to one or more phone numbers (purchase tracking numbers).\n\nPurchases numbers from Telnyx, charges immediately, and creates monthly usage entries.\n\nRequest body:\n- phone_numbers: List of phone numbers to purchase (e.g., [\"+351256259001\", \"+351256259002\"])\n- team_id: Team ID to assign the numbers to\n- forward_to: Number to forward calls to\n- idpointofsale: (Optional) PV ID for billing (defaults to team's PV)\n\nReturns:\n- subscribed: List of successfully purchased numbers\n- failed: List of numbers that failed to purchase\n- already_subscribed: List of numbers already owned","operationId":"subscribe_to_phone_api_phone_subscribe_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Subscribe To Phone Api Phone Subscribe Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/phone/unsubscribe/{tracking_number_id}":{"delete":{"tags":["Phone Subscription"],"summary":"Unsubscribe from phone number (release tracking number)","description":"Unsubscribe from a phone number (release tracking number).\n\nReleases the number from Telnyx and ends the monthly usage entry.\n\nArgs:\n    tracking_number_id: The tracking number ID to unsubscribe","operationId":"unsubscribe_from_phone_api_phone_unsubscribe__tracking_number_id__delete","parameters":[{"name":"tracking_number_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Tracking Number Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unsubscribe From Phone Api Phone Unsubscribe  Tracking Number Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/phone/subscriptions":{"get":{"tags":["Phone Subscription"],"summary":"List active phone rental subscriptions","description":"List all active phone rental subscriptions for the company.\n\nReturns list of tracking numbers with subscription details.","operationId":"list_phone_subscriptions_api_phone_subscriptions_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Phone Subscriptions Api Phone Subscriptions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tickets":{"post":{"tags":["Tickets"],"summary":"Create a new ticket","description":"Create a support ticket with optional file attachments.","operationId":"create_ticket_api_tickets_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_ticket_api_tickets_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Tickets"],"summary":"List my company's tickets","description":"List tickets for the authenticated user's company.","operationId":"list_tickets_api_tickets_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by status","title":"Status"},"description":"Filter by status"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tickets/{ticket_id}":{"get":{"tags":["Tickets"],"summary":"Get ticket detail","description":"Get a ticket with all messages and attachments.","operationId":"get_ticket_api_tickets__ticket_id__get","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Ticket Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tickets/{ticket_id}/messages":{"post":{"tags":["Tickets"],"summary":"Reply to a ticket","description":"Add a message/reply to a ticket.","operationId":"add_message_api_tickets__ticket_id__messages_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Ticket Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_add_message_api_tickets__ticket_id__messages_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tickets/{ticket_id}/attachments/{attachment_id}/download":{"get":{"tags":["Tickets"],"summary":"Download a ticket attachment","description":"Get a presigned URL to download a ticket attachment.","operationId":"download_attachment_api_tickets__ticket_id__attachments__attachment_id__download_get","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Ticket Id"}},{"name":"attachment_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Attachment Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/tickets/assignees":{"get":{"tags":["Tickets - Admin"],"summary":"List assignable admins","description":"Get all system_admin users for ticket assignment dropdown.","operationId":"admin_list_assignees_api_admin_tickets_assignees_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/tickets":{"post":{"tags":["Tickets - Admin"],"summary":"Create ticket (admin)","description":"Create a ticket from the system-admin flow.\n\nMirrors the user create endpoint but allows admin-only categories\n(integracoes) and an internal priority, and always validates assigned_to.\n\nThe ticket carries the acting admin's HOME company — never the one they may\nbe impersonating. `user[\"idcompany\"]` is ambient (see auth.home_company): an\nadmin who switched into a tenant and then opened the system-admin panel would\notherwise file this internal ticket INSIDE that tenant, where the tenant read\npath (`db.tickets.list_tickets_by_company`, which filters on idcompany alone)\nmakes it readable by their users, and the attachment prefix below drops the\nfiles into that tenant's MultiDrive.","operationId":"admin_create_ticket_api_admin_tickets_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_admin_create_ticket_api_admin_tickets_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Tickets - Admin"],"summary":"List all tickets (admin)","description":"List all tickets across every company (admin view). limit=0 fetches all.\n\nSystem_admin only (see admin_router dependencies). Not scoped to the\ncaller's queue — every ticket in the system is returned so the admin\npage can filter by company / assignee / state client-side.","operationId":"admin_list_tickets_api_admin_tickets_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"idcompany","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idcompany"}},{"name":"assigned_to","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Assigned To"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/tickets/{ticket_id}":{"get":{"tags":["Tickets - Admin"],"summary":"Get ticket detail (admin)","description":"Cross-tenant ticket detail. Mirrors GET /tickets/{id} but without the\n`idcompany` filter — system_admin only (see admin_router dependencies).","operationId":"admin_get_ticket_api_admin_tickets__ticket_id__get","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Ticket Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Tickets - Admin"],"summary":"Update ticket (admin)","description":"Update ticket status, priority, internal priority, assignment, or category.\n\nassigned_to and internal_priority accept an explicit null to CLEAR the field\n(unassign / revert to the user's priority) — absent means \"don't touch\"\n(discriminated via Pydantic v2 model_fields_set).","operationId":"admin_update_ticket_api_admin_tickets__ticket_id__put","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Ticket Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/tickets/{ticket_id}/messages":{"post":{"tags":["Tickets - Admin"],"summary":"Admin reply to ticket","description":"Admin reply to a ticket (is_admin=1).","operationId":"admin_add_message_api_admin_tickets__ticket_id__messages_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Ticket Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_admin_add_message_api_admin_tickets__ticket_id__messages_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/tickets/{ticket_id}/notes":{"get":{"tags":["Tickets - Admin"],"summary":"List internal notes + activity (admin)","description":"Internal notes ('note') and timeline events ('event') for a ticket.\n\nADMIN-ONLY — the submitting user must never see this data. The FE splits\nthe single chronological stream by note_type.","operationId":"admin_list_notes_api_admin_tickets__ticket_id__notes_get","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Ticket Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Tickets - Admin"],"summary":"Add internal note (admin)","description":"Add an internal note visible only to system admins.\n\nNo closed-status gate (contrast with the user reply endpoint): notes are\ninternal coordination and must remain possible on closed/resolved tickets —\nsafe because create_internal_note never bumps the ticket's updated_at.","operationId":"admin_add_note_api_admin_tickets__ticket_id__notes_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Ticket Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_admin_add_note_api_admin_tickets__ticket_id__notes_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dashboard/leads":{"get":{"tags":["Dashboard Overview"],"summary":"Leads overview for dashboard","operationId":"dashboard_leads_api_dashboard_leads_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by year","title":"Year"},"description":"Filter by year"},{"name":"month","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Filter by month(s) within year","default":[],"title":"Month"},"description":"Filter by month(s) within year"},{"name":"teams_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Filter by attribution funnel(s) — Z_Leads.teams_id, not owner membership","default":[],"title":"Teams Id"},"description":"Filter by attribution funnel(s) — Z_Leads.teams_id, not owner membership"},{"name":"include_no_funnel","in":"query","required":false,"schema":{"type":"boolean","description":"Also match leads with no (or an orphaned) attribution funnel","default":false,"title":"Include No Funnel"},"description":"Also match leads with no (or an orphaned) attribution funnel"},{"name":"sort_sellers_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort salespeople by: 'sales' (won count), 'value' (won value), 'profit' (vehicle margin). Default: total leads","title":"Sort Sellers By"},"description":"Sort salespeople by: 'sales' (won count), 'value' (won value), 'profit' (vehicle margin). Default: total leads"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Dashboard Leads Api Dashboard Leads Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dashboard/vehicles":{"get":{"tags":["Dashboard Overview"],"summary":"Vehicles overview for dashboard","operationId":"dashboard_vehicles_api_dashboard_vehicles_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by year (for sold count)","title":"Year"},"description":"Filter by year (for sold count)"},{"name":"month","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Filter by month(s) within year","default":[],"title":"Month"},"description":"Filter by month(s) within year"},{"name":"idpointofsale","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Filter by point(s) of sale (omit for global)","default":[],"title":"Idpointofsale"},"description":"Filter by point(s) of sale (omit for global)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Dashboard Vehicles Api Dashboard Vehicles Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dashboard/website":{"get":{"tags":["Dashboard Overview"],"summary":"Website analytics overview for dashboard","description":"Website stats are always global (websites are linked to brands, not PVs).","operationId":"dashboard_website_api_dashboard_website_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by year","title":"Year"},"description":"Filter by year"},{"name":"month","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Filter by month(s) within year","default":[],"title":"Month"},"description":"Filter by month(s) within year"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Dashboard Website Api Dashboard Website Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dashboard/financial":{"get":{"tags":["Dashboard Overview"],"summary":"Financial overview for dashboard","operationId":"dashboard_financial_api_dashboard_financial_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by year","title":"Year"},"description":"Filter by year"},{"name":"month","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Filter by month(s) within year","default":[],"title":"Month"},"description":"Filter by month(s) within year"},{"name":"idpointofsale","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Filter by point(s) of sale (omit for global)","default":[],"title":"Idpointofsale"},"description":"Filter by point(s) of sale (omit for global)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Dashboard Financial Api Dashboard Financial Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dashboard/cash":{"get":{"tags":["Dashboard Overview"],"summary":"Cash overview for dashboard","operationId":"dashboard_cash_api_dashboard_cash_get","parameters":[{"name":"idpointofsale","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Filter by point(s) of sale (omit for global)","default":[],"title":"Idpointofsale"},"description":"Filter by point(s) of sale (omit for global)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Dashboard Cash Api Dashboard Cash Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dashboard/activity":{"get":{"tags":["Dashboard Overview"],"summary":"Activity feed & alerts for dashboard","operationId":"dashboard_activity_api_dashboard_activity_get","parameters":[{"name":"idpointofsale","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Filter by point(s) of sale (omit for global)","default":[],"title":"Idpointofsale"},"description":"Filter by point(s) of sale (omit for global)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Dashboard Activity Api Dashboard Activity Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dashboard/metas":{"get":{"tags":["Dashboard - Metas"],"summary":"Registo de métricas + metas da empresa","operationId":"get_metas_api_dashboard_metas_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Dashboard - Metas"],"summary":"Definir/atualizar uma meta","operationId":"upsert_meta_api_dashboard_metas_put","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dashboard/metas/{meta_id}":{"delete":{"tags":["Dashboard - Metas"],"summary":"Remover uma meta","operationId":"delete_meta_api_dashboard_metas__meta_id__delete","parameters":[{"name":"meta_id","in":"path","required":true,"schema":{"type":"integer","minimum":1,"title":"Meta Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/holidays":{"get":{"tags":["Holidays"],"summary":"List effective holidays for a year","operationId":"api_get_holidays_api_holidays_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"type":"integer","description":"Year (defaults to current year)","title":"Year"},"description":"Year (defaults to current year)"},{"name":"idpointofsale","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Scope to a specific PV (defaults to all PVs of the company)","title":"Idpointofsale"},"description":"Scope to a specific PV (defaults to all PVs of the company)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Holidays"],"summary":"Add a custom company holiday","operationId":"api_add_holiday_api_holidays_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/holidays/seed/{year}":{"post":{"tags":["Holidays"],"summary":"Populate the global holidays catalog for a year (nationals + municipals)","description":"Idempotently seeds Z_HolidaysCatalog with Portuguese national and municipal\nholidays for the given year. The catalog is global (no idcompany), shared\nacross all tenants. Each company then chooses which of these apply to them\nby hiding the ones they don't observe or adding their own customs.","operationId":"api_seed_catalog_api_holidays_seed__year__post","parameters":[{"name":"year","in":"path","required":true,"schema":{"type":"integer","exclusiveMaximum":2100,"exclusiveMinimum":2000,"title":"Year"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/holidays/{holiday_id}":{"delete":{"tags":["Holidays"],"summary":"Delete a custom company holiday","operationId":"api_delete_holiday_api_holidays__holiday_id__delete","parameters":[{"name":"holiday_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Holiday Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/holidays/hide/{catalog_id}":{"post":{"tags":["Holidays"],"summary":"Hide a catalog holiday for the current company","operationId":"api_hide_holiday_api_holidays_hide__catalog_id__post","parameters":[{"name":"catalog_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Catalog Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Holidays"],"summary":"Un-hide a previously hidden catalog holiday","operationId":"api_unhide_holiday_api_holidays_hide__catalog_id__delete","parameters":[{"name":"catalog_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Catalog Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/schedules":{"get":{"tags":["Work Schedules"],"summary":"List work schedules","operationId":"api_list_schedules_api_schedules_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Work Schedules"],"summary":"Create a work schedule","operationId":"api_create_schedule_api_schedules_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/schedules/{schedule_id}":{"put":{"tags":["Work Schedules"],"summary":"Update a work schedule","operationId":"api_update_schedule_api_schedules__schedule_id__put","parameters":[{"name":"schedule_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Schedule Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Work Schedules"],"summary":"Delete a work schedule","operationId":"api_delete_schedule_api_schedules__schedule_id__delete","parameters":[{"name":"schedule_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Schedule Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/schedules/assign":{"post":{"tags":["Work Schedules"],"summary":"Assign employee to schedule","operationId":"api_assign_schedule_api_schedules_assign_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/schedules/employee/{user_id}":{"get":{"tags":["Work Schedules"],"summary":"Get employee's current schedule","operationId":"api_get_employee_schedule_api_schedules_employee__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/qr/current":{"get":{"tags":["Attendance"],"summary":"Get current QR code for display","description":"Returns the current valid QR code token and its expiry.\nDisplay this as a QR code on a tablet/screen at the workplace.\nFrontend should poll this endpoint or use valid_until to auto-refresh.","operationId":"api_get_current_qr_api_attendance_qr_current_get","parameters":[{"name":"idpointofsale","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Optional POS scope","title":"Idpointofsale"},"description":"Optional POS scope"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/clock":{"post":{"tags":["Attendance"],"summary":"Clock in/out via QR code","description":"Employee scans QR code to clock in or out.\nAuto-detects whether this is a clock-in or clock-out based on last record.\nRequires: { \"code\": \"qr_token_string\" }","operationId":"api_clock_via_qr_api_attendance_clock_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/clock/manual":{"post":{"tags":["Attendance"],"summary":"Manual clock entry (admin)","description":"Admin creates a manual attendance entry for an employee.\nRequires: { \"id_utilizador\": int, \"record_type\": \"clock_in\"|\"clock_out\", \"recorded_at\": \"ISO datetime\" }","operationId":"api_manual_clock_api_attendance_clock_manual_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/records/{record_id}":{"put":{"tags":["Attendance"],"summary":"Edit an attendance record (admin)","description":"Admin edits an attendance record. Non-destructive: a corrected row is\ninserted (method='admin_edit') and the old row is marked superseded, so the\nfull history is preserved.\n\nRequires: { \"record_type\": \"clock_in\"|\"clock_out\", \"recorded_at\": \"ISO datetime\", \"notes\"?: str }","operationId":"api_edit_record_api_attendance_records__record_id__put","parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"integer","title":"Record Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Attendance"],"summary":"Delete an attendance record (admin)","description":"Admin deletes an attendance record. Non-destructive: the row is tombstoned\n(voided_at/voided_by stamped) and hidden from every read, never physically\nremoved — these are labour-law compliance records.","operationId":"api_delete_record_api_attendance_records__record_id__delete","parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"integer","title":"Record Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/clock/geo":{"post":{"tags":["Attendance"],"summary":"Clock in/out via geolocation","description":"Employee clocks in/out by sending their GPS coordinates.\nValidates proximity to an allowed POS within geofence radius.\n\nRequires: { \"latitude\": float, \"longitude\": float, \"accuracy\": float (optional) }","operationId":"api_clock_via_geo_api_attendance_clock_geo_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/settings/{idpointofsale}":{"get":{"tags":["Attendance"],"summary":"Get attendance settings for a POS","operationId":"api_get_attendance_settings_api_attendance_settings__idpointofsale__get","parameters":[{"name":"idpointofsale","in":"path","required":true,"schema":{"type":"integer","title":"Idpointofsale"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Attendance"],"summary":"Update attendance settings for a POS","operationId":"api_update_attendance_settings_api_attendance_settings__idpointofsale__put","parameters":[{"name":"idpointofsale","in":"path","required":true,"schema":{"type":"integer","title":"Idpointofsale"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/settings":{"get":{"tags":["Attendance"],"summary":"Get all POS with attendance settings, links and subscriptions","description":"Bulk endpoint: returns all POS for the company with their attendance settings,\nactive link, coordinates, and subscription count.\nOne request instead of N per-POS fetches.","operationId":"api_get_all_attendance_settings_api_attendance_settings_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/links":{"post":{"tags":["Attendance"],"summary":"Generate a shareable attendance link","description":"Generate a dedicated attendance link for a tablet/screen.\nReturns a URL that can be opened without login.\n\nBody (optional): { \"idpointofsale\": 1, \"description\": \"Tablet do Stand Lisboa\" }","operationId":"api_generate_link_api_attendance_links_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Attendance"],"summary":"List attendance links","description":"List all attendance links for the company.","operationId":"api_list_links_api_attendance_links_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/links/{link_id}":{"delete":{"tags":["Attendance"],"summary":"Deactivate an attendance link","description":"Deactivate an attendance link (tablet URL stops working).","operationId":"api_deactivate_link_api_attendance_links__link_id__delete","parameters":[{"name":"link_id","in":"path","required":true,"schema":{"type":"integer","title":"Link Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/records":{"get":{"tags":["Attendance"],"summary":"List attendance records","operationId":"api_get_records_api_attendance_records_get","parameters":[{"name":"id_utilizador","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Utilizador"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"YYYY-MM-DD","title":"Date From"},"description":"YYYY-MM-DD"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"YYYY-MM-DD","title":"Date To"},"description":"YYYY-MM-DD"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/records/today":{"get":{"tags":["Attendance"],"summary":"Get today's records for current user","operationId":"api_get_today_api_attendance_records_today_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/summary":{"get":{"tags":["Attendance"],"summary":"Daily attendance summary","operationId":"api_get_summary_api_attendance_summary_get","parameters":[{"name":"date_from","in":"query","required":true,"schema":{"type":"string","description":"YYYY-MM-DD","title":"Date From"},"description":"YYYY-MM-DD"},{"name":"date_to","in":"query","required":true,"schema":{"type":"string","description":"YYYY-MM-DD","title":"Date To"},"description":"YYYY-MM-DD"},{"name":"id_utilizador","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Utilizador"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/overtime":{"get":{"tags":["Attendance"],"summary":"Overtime report","operationId":"api_get_overtime_api_attendance_overtime_get","parameters":[{"name":"date_from","in":"query","required":true,"schema":{"type":"string","description":"YYYY-MM-DD","title":"Date From"},"description":"YYYY-MM-DD"},{"name":"date_to","in":"query","required":true,"schema":{"type":"string","description":"YYYY-MM-DD","title":"Date To"},"description":"YYYY-MM-DD"},{"name":"id_utilizador","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Utilizador"}},{"name":"daily_hours_limit","in":"query","required":false,"schema":{"type":"number","description":"Normal daily hours (default 8)","default":8.0,"title":"Daily Hours Limit"},"description":"Normal daily hours (default 8)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/subscribe":{"post":{"tags":["Attendance"],"summary":"Subscribe users to livro de ponto","description":"Subscribe one or more employees to livro de ponto.\nCharges per user per month from the user's PV credits.\n\nBody: { \"user_ids\": [456, 789] }\nOr:   { \"emails\": [\"john@example.com\"] }  (for invited users not yet onboarded)","operationId":"api_subscribe_attendance_api_attendance_subscribe_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/subscribe/{user_id}":{"delete":{"tags":["Attendance"],"summary":"Unsubscribe user from livro de ponto","description":"Unsubscribe an employee from livro de ponto.","operationId":"api_unsubscribe_attendance_api_attendance_subscribe__user_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attendance/subscriptions":{"get":{"tags":["Attendance"],"summary":"List livro de ponto subscriptions","description":"List all active livro de ponto subscriptions for the company.","operationId":"api_list_attendance_subscriptions_api_attendance_subscriptions_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaves":{"post":{"tags":["Leave Management"],"summary":"Submit a leave request","description":"Submit a leave request with optional document upload.\nUses multipart/form-data.\nDocument is required for certain leave types (baixa_doenca, casamento, etc.).\nMax file size: 2MB. Allowed: PDF, JPG, PNG, DOC, DOCX.","operationId":"api_create_leave_api_leaves_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_api_create_leave_api_leaves_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Leave Management"],"summary":"List leave requests","operationId":"api_list_leaves_api_leaves_get","parameters":[{"name":"id_utilizador","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Utilizador"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"leave_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Leave Type"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date To"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaves/types":{"get":{"tags":["Leave Management"],"summary":"Get leave types metadata","description":"Returns leave types with info about document requirements and day limits.","operationId":"api_get_leave_types_api_leaves_types_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaves/balances":{"get":{"tags":["Leave Management"],"summary":"Get current user's leave balance","operationId":"api_get_balance_api_leaves_balances_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaves/balances/team":{"get":{"tags":["Leave Management"],"summary":"Get team leave balances","operationId":"api_get_team_balances_api_leaves_balances_team_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaves/calendar":{"get":{"tags":["Leave Management"],"summary":"Team leave calendar","operationId":"api_get_calendar_api_leaves_calendar_get","parameters":[{"name":"month","in":"query","required":true,"schema":{"type":"integer","maximum":12,"minimum":1,"title":"Month"}},{"name":"year","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Year"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaves/{leave_id}":{"get":{"tags":["Leave Management"],"summary":"Get leave request details","operationId":"api_get_leave_api_leaves__leave_id__get","parameters":[{"name":"leave_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Leave Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaves/{leave_id}/approve":{"put":{"tags":["Leave Management"],"summary":"Approve a leave request","operationId":"api_approve_leave_api_leaves__leave_id__approve_put","parameters":[{"name":"leave_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Leave Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaves/{leave_id}/reject":{"put":{"tags":["Leave Management"],"summary":"Reject a leave request","operationId":"api_reject_leave_api_leaves__leave_id__reject_put","parameters":[{"name":"leave_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Leave Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaves/{leave_id}/cancel":{"put":{"tags":["Leave Management"],"summary":"Cancel own leave request","operationId":"api_cancel_leave_api_leaves__leave_id__cancel_put","parameters":[{"name":"leave_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Leave Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/company/vacation-config":{"get":{"tags":["Vacation Management"],"summary":"Get the company's vacation base-days config","operationId":"api_get_vacation_config_api_company_vacation_config_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Vacation Management"],"summary":"Update the company's vacation base-days config","operationId":"api_update_vacation_config_api_company_vacation_config_patch","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vacation-balance/workers":{"get":{"tags":["Vacation Management"],"summary":"List worker vacation balances for a year (admin view)","operationId":"api_get_worker_balances_api_vacation_balance_workers_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vacation-balance/worker/{id_utilizador}/adjust":{"patch":{"tags":["Vacation Management"],"summary":"Manually adjust a worker's vacation balance","operationId":"api_adjust_worker_balance_api_vacation_balance_worker__id_utilizador__adjust_patch","parameters":[{"name":"id_utilizador","in":"path","required":true,"schema":{"type":"integer","title":"Id Utilizador"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vacation-balance/rollover":{"post":{"tags":["Vacation Management"],"summary":"Manually trigger year-end vacation rollover (idempotent)","operationId":"api_run_rollover_api_vacation_balance_rollover_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/vacation-balance/audit-log":{"get":{"tags":["Vacation Management"],"summary":"List vacation balance audit log (admin)","operationId":"api_list_audit_log_api_vacation_balance_audit_log_get","parameters":[{"name":"id_utilizador","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Utilizador"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/api-tokens":{"get":{"tags":["API Tokens"],"summary":"List company API tokens","description":"List all API tokens for the current company. Returns metadata only (no secrets).","operationId":"api_list_tokens_api_api_tokens_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["API Tokens"],"summary":"Generate a new API token","description":"Generate a new API token for the company.\nThe raw token is returned ONCE in the response — it cannot be retrieved again.\nStore it securely.","operationId":"api_generate_token_api_api_tokens_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/api-tokens/{token_id}":{"delete":{"tags":["API Tokens"],"summary":"Revoke an API token","description":"Permanently revoke/delete an API token.","operationId":"api_revoke_token_api_api_tokens__token_id__delete","parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Token Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ad-config":{"get":{"tags":["Ad Config"],"summary":"Get Config","description":"Get the ad generation template config for a PV.","operationId":"get_config_api_ad_config_get","parameters":[{"name":"pv_id","in":"query","required":false,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Ad Config"],"summary":"Save Config","description":"Save/update the ad generation template config for a PV.","operationId":"save_config_api_ad_config_put","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/config":{"get":{"tags":["toc-online"],"summary":"Get TOC Online configuration for the company","description":"Fetch current TOC Online config for the user's PV (masks tokens).","operationId":"get_toc_config_api_toc_config_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Toc Config Api Toc Config Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["toc-online"],"summary":"Update TOC Online configuration for the company","description":"Insert or update TOC Online credentials for the company/PV.","operationId":"update_toc_config_api_toc_config_put","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Toc Config Api Toc Config Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/invoices":{"post":{"tags":["toc-online"],"summary":"Create invoice in TOC Online","description":"Create an invoice directly from JSON payload via TOC Online API.\n\nNo TOC_DocVenda or Vendas tables needed — everything in one request.\nAutomatically creates a Faturas entry with the S3 PDF path.\n\nRequired fields:\n- nif_cliente (str): Customer NIF\n- document_type (str): FT, FR, FS, NC, or ND\n- document_series_prefix (str): e.g. \"2024\", \"2025\"\n- lines (array): [{description, quantity, unit_price, ...}]\n\nOptional fields:\n- date, due_date, payment_mechanism, operation_country\n- tax_exemption_reason_id, bank_account_id, cash_account_id\n- download_pdf (bool, default true)","operationId":"create_invoice_api_toc_invoices_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Invoice Api Toc Invoices Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/creditable-invoices":{"get":{"tags":["toc-online"],"summary":"Search company sale invoices a Nota de Crédito can reference","description":"Company-wide (ALL points of sale) list of sale invoices (FT/FR/FS) that can be\nreferenced as the origin of a Nota de Crédito. Feeds the NC origin picker in the\n\"Criar Fatura TOC Online\" dialog; the selected invoice's document number (G) is\nsent to TOConline as parent_document_reference.","operationId":"get_creditable_invoices_api_toc_creditable_invoices_get","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Match by document number (G) or ATCUD (H)","title":"Search"},"description":"Match by document number (G) or ATCUD (H)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Creditable Invoices Api Toc Creditable Invoices Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/series":{"get":{"tags":["toc-online"],"summary":"Get document series from TOC","description":"Fetch available document series for invoice creation.","operationId":"get_series_api_toc_series_get","parameters":[{"name":"document_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"FT, FR, FS, NC, ND","title":"Document Type"},"description":"FT, FR, FS, NC, ND"},{"name":"prefix","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Series prefix e.g. 2024","title":"Prefix"},"description":"Series prefix e.g. 2024"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Series Api Toc Series Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/taxes":{"get":{"tags":["toc-online"],"summary":"Get tax rates from TOC","description":"Fetch tax rates for correct VAT calculations.","operationId":"get_taxes_api_toc_taxes_get","parameters":[{"name":"tax_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"NOR, INT, RED, ISE","title":"Tax Code"},"description":"NOR, INT, RED, ISE"},{"name":"tax_country_region","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"PT, PT-AC, PT-MA","title":"Tax Country Region"},"description":"PT, PT-AC, PT-MA"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Taxes Api Toc Taxes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/products":{"get":{"tags":["toc-online"],"summary":"Get products from TOC","description":"Fetch pre-configured products from TOC.","operationId":"get_products_api_toc_products_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Product code filter","title":"Code"},"description":"Product code filter"},{"name":"description","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Description filter","title":"Description"},"description":"Description filter"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Products Api Toc Products Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/services":{"get":{"tags":["toc-online"],"summary":"Get services from TOC","description":"Fetch pre-configured services from TOC.","operationId":"get_services_api_toc_services_get","parameters":[{"name":"description","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Description filter","title":"Description"},"description":"Description filter"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Services Api Toc Services Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/bank-accounts":{"get":{"tags":["toc-online"],"summary":"Get bank accounts from TOC","description":"Fetch bank accounts for invoice payment configuration.","operationId":"get_bank_accounts_api_toc_bank_accounts_get","parameters":[{"name":"entity_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User or Supplier","title":"Entity Type"},"description":"User or Supplier"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Bank Accounts Api Toc Bank Accounts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/cash-accounts":{"get":{"tags":["toc-online"],"summary":"Get cash accounts from TOC","description":"Fetch cash accounts from TOC.","operationId":"get_cash_accounts_api_toc_cash_accounts_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Cash Accounts Api Toc Cash Accounts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/countries":{"get":{"tags":["toc-online"],"summary":"Get country codes from TOC","description":"Fetch country codes for operation_country field.","operationId":"get_countries_api_toc_countries_get","parameters":[{"name":"iso_alpha_2","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"e.g. PT, ES, FR","title":"Iso Alpha 2"},"description":"e.g. PT, ES, FR"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Countries Api Toc Countries Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/units-of-measure":{"get":{"tags":["toc-online"],"summary":"Get units of measure from TOC","description":"Fetch units of measure from TOC.","operationId":"get_units_of_measure_api_toc_units_of_measure_get","parameters":[{"name":"unit","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"e.g. Un, Kg, L","title":"Unit"},"description":"e.g. Un, Kg, L"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Units Of Measure Api Toc Units Of Measure Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/tax-exemption-reasons":{"get":{"tags":["toc-online"],"summary":"Get tax exemption reasons from TOC","description":"Fetch tax exemption reasons for ISE (VAT-exempt) lines.","operationId":"get_tax_exemption_reasons_api_toc_tax_exemption_reasons_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Tax Exemption Reasons Api Toc Tax Exemption Reasons Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc/pv-status":{"get":{"tags":["toc-online"],"summary":"Get TOC Online configuration status per point of sale","description":"Returns all PVs for the company with their TOC Online match status.\nEach PV includes: id, name, nipc, toc_configured (bool), toc_online_id (int|null).","operationId":"get_pv_toc_status_api_toc_pv_status_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Pv Toc Status Api Toc Pv Status Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai-pricing":{"get":{"tags":["AI Pricer"],"summary":"Internal Ai Pricing","description":"Internal dealership pricing with real market data.\nNo email/phone required. Returns pricing + market data + source listings.","operationId":"internal_ai_pricing_api_ai_pricing_get","parameters":[{"name":"marca","in":"query","required":true,"schema":{"type":"string","title":"Marca"}},{"name":"modelo","in":"query","required":true,"schema":{"type":"string","title":"Modelo"}},{"name":"kms","in":"query","required":true,"schema":{"type":"integer","title":"Kms"}},{"name":"year","in":"query","required":true,"schema":{"type":"integer","title":"Year"}},{"name":"fuel","in":"query","required":true,"schema":{"type":"string","title":"Fuel"}},{"name":"version","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version"}},{"name":"doors","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Doors"}},{"name":"engine_capacity","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Engine Capacity"}},{"name":"power","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Power"}},{"name":"gearbox","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gearbox"}},{"name":"vehicle_type","in":"query","required":false,"schema":{"enum":["car","moto","comercial","pesado"],"type":"string","description":"Vehicle category — picks scraper section + AI prompt variant","default":"car","title":"Vehicle Type"},"description":"Vehicle category — picks scraper section + AI prompt variant"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai-pricing/leads/{lead_id}":{"get":{"tags":["AI Pricer"],"summary":"Get Appraisals By Lead","description":"Get appraisals linked to a specific lead.","operationId":"get_appraisals_by_lead_api_ai_pricing_leads__lead_id__get","parameters":[{"name":"lead_id","in":"path","required":true,"schema":{"type":"integer","title":"Lead Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai-pricing/history":{"get":{"tags":["AI Pricer"],"summary":"List Appraisal History","description":"List appraisal history for the authenticated user's company.","operationId":"list_appraisal_history_api_ai_pricing_history_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Q"}},{"name":"brand","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Brand"}},{"name":"model","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Model"}},{"name":"unattached_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Unattached Only"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"title":"Date To"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","pattern":"^(newest|oldest)$","default":"newest","title":"Sort"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["AI Pricer"],"summary":"Save Appraisal History","description":"Save an appraisal result to persistent history.","operationId":"save_appraisal_history_api_ai_pricing_history_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai-pricing/history/{appraisal_id}":{"get":{"tags":["AI Pricer"],"summary":"Get Appraisal History Item","description":"Fetch a single appraisal history record by id, tenant-scoped.","operationId":"get_appraisal_history_item_api_ai_pricing_history__appraisal_id__get","parameters":[{"name":"appraisal_id","in":"path","required":true,"schema":{"type":"integer","title":"Appraisal Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["AI Pricer"],"summary":"Delete Appraisal History","description":"Delete an appraisal from history.","operationId":"delete_appraisal_history_api_ai_pricing_history__appraisal_id__delete","parameters":[{"name":"appraisal_id","in":"path","required":true,"schema":{"type":"integer","title":"Appraisal Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai-pricing/history/{appraisal_id}/margin":{"patch":{"tags":["AI Pricer"],"summary":"Update Appraisal History Margin","description":"Persist an adjusted dealer margin onto an existing appraisal row.\n\nBody: { margin_percent: number, min_margin_euros: number }. The seller\npayout and commission are recomputed server-side from the stored\n`market_value_likely`, so the saved figures always match the \"Ajustar\nMargem\" panel. Tenant-scoped.","operationId":"update_appraisal_history_margin_api_ai_pricing_history__appraisal_id__margin_patch","parameters":[{"name":"appraisal_id","in":"path","required":true,"schema":{"type":"integer","title":"Appraisal Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai-pricing/settings":{"get":{"tags":["AI Pricer"],"summary":"Get Pricer Settings","description":"Get AI pricer margin settings for the authenticated user's company.","operationId":"get_pricer_settings_api_ai_pricing_settings_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["AI Pricer"],"summary":"Update Pricer Settings","description":"Save AI pricer margin settings for the authenticated user's company.","operationId":"update_pricer_settings_api_ai_pricing_settings_put","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai-pricing/selling-estimate":{"post":{"tags":["AI Pricer"],"summary":"Selling Price Estimate","description":"Estimate a retail selling price for a vehicle already owned by the dealership.\n\nBody: { vehicle_id, marca, modelo, year, kms, fuel, version?, doors?,\n        engine_capacity?, power?, gearbox? }\n\nReturns three price bands (min / recommended / max) from the AI + market\nscraper pipeline, plus the company's configured margin and a comparison\nagainst the vehicle's current stored price (Viatura.Preço).","operationId":"selling_price_estimate_api_ai_pricing_selling_estimate_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/domains":{"get":{"tags":["Marketing"],"summary":"List Domains","description":"List all marketing domains for the company.","operationId":"list_domains_api_marketing_domains_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Marketing"],"summary":"Add Domain","description":"Register new domain and initiate SES verification.","operationId":"add_domain_api_marketing_domains_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/domains/{domain_id}/status":{"get":{"tags":["Marketing"],"summary":"Check Domain Status","description":"Check verification status of a domain from SES.","operationId":"check_domain_status_api_marketing_domains__domain_id__status_get","parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"integer","title":"Domain Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/domains/{domain_id}":{"delete":{"tags":["Marketing"],"summary":"Delete Domain","description":"Delete a domain and remove from SES.","operationId":"delete_domain_api_marketing_domains__domain_id__delete","parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"integer","title":"Domain Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/templates/placeholders":{"get":{"tags":["Marketing"],"summary":"List Template Placeholders","description":"List merge-tag placeholders available in the template editor.","operationId":"list_template_placeholders_api_marketing_templates_placeholders_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/templates":{"get":{"tags":["Marketing"],"summary":"List Templates","description":"List email templates (paginated).","operationId":"list_templates_api_marketing_templates_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Marketing"],"summary":"Create Template","description":"Create a new email template (manual HTML/CSS).","operationId":"create_template_api_marketing_templates_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/templates/{template_id}":{"get":{"tags":["Marketing"],"summary":"Get Template","description":"Get single template with full HTML content.","operationId":"get_template_api_marketing_templates__template_id__get","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Marketing"],"summary":"Update Template","description":"Update an existing template.","operationId":"update_template_api_marketing_templates__template_id__put","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Marketing"],"summary":"Delete Template","description":"Soft-delete a template.","operationId":"delete_template_api_marketing_templates__template_id__delete","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/templates/ai-generate":{"post":{"tags":["Marketing"],"summary":"Ai Generate Template","description":"Queue an async AI marketing template generation job.\n\nReturns immediately with a job_id — the actual Claude call runs in a\nbackground thread (can take 60-120s+). Poll the status via\nGET /templates/ai-generate/{job_id}.","operationId":"ai_generate_template_api_marketing_templates_ai_generate_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/templates/ai-generate/{job_id}":{"get":{"tags":["Marketing"],"summary":"Get Ai Generate Job","description":"Poll the status of an async AI template generation job.\n\nTenant-scoped — returns 404 for jobs belonging to other companies.","operationId":"get_ai_generate_job_api_marketing_templates_ai_generate__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"integer","title":"Job Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns":{"get":{"tags":["Marketing"],"summary":"List Campaigns","description":"List campaigns (paginated, optional status filter).\n\nAuto-generated recurring occurrences (children) are hidden here — they're\nviewed per-parent via /campaigns/recurring/{id}/occurrences.","operationId":"list_campaigns_api_marketing_campaigns_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Marketing"],"summary":"Create Campaign","description":"Create a new campaign (draft status).","operationId":"create_campaign_api_marketing_campaigns_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/schedule-recurring":{"post":{"tags":["Marketing"],"summary":"Schedule Campaign Recurring","description":"Promote a draft campaign into a recurring parent (daily/weekly/monthly).","operationId":"schedule_campaign_recurring_api_marketing_campaigns__campaign_id__schedule_recurring_post","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/recurring/{campaign_id}":{"put":{"tags":["Marketing"],"summary":"Update Recurring Campaign","description":"Edit a recurring campaign's schedule (frequency/day/time/end) + recompute next run.","operationId":"update_recurring_campaign_api_marketing_campaigns_recurring__campaign_id__put","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/recurring":{"get":{"tags":["Marketing"],"summary":"List Recurring Campaigns","description":"List this company's recurring campaign parents.","operationId":"list_recurring_campaigns_api_marketing_campaigns_recurring_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/recurring/{campaign_id}/occurrences":{"get":{"tags":["Marketing"],"summary":"List Recurring Occurrences","description":"List the past/queued occurrences (children) of a recurring parent.","operationId":"list_recurring_occurrences_api_marketing_campaigns_recurring__campaign_id__occurrences_get","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/recurring/{campaign_id}/pause":{"post":{"tags":["Marketing"],"summary":"Pause Recurring Campaign","description":"Pause a recurring campaign (stops future occurrences; in-flight child unaffected).","operationId":"pause_recurring_campaign_api_marketing_campaigns_recurring__campaign_id__pause_post","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/recurring/{campaign_id}/resume":{"post":{"tags":["Marketing"],"summary":"Resume Recurring Campaign","description":"Resume a recurring campaign, re-anchoring next_run_at to the next future slot.","operationId":"resume_recurring_campaign_api_marketing_campaigns_recurring__campaign_id__resume_post","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}":{"get":{"tags":["Marketing"],"summary":"Get Campaign","description":"Get campaign with stats and template info.","operationId":"get_campaign_api_marketing_campaigns__campaign_id__get","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Marketing"],"summary":"Update Campaign","description":"Update a campaign's settings (draft or recurring parent).","operationId":"update_campaign_api_marketing_campaigns__campaign_id__put","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Marketing"],"summary":"Delete Campaign","description":"Delete a draft campaign.","operationId":"delete_campaign_api_marketing_campaigns__campaign_id__delete","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/schedule":{"post":{"tags":["Marketing"],"summary":"Schedule Campaign","description":"Schedule a campaign for a future time.\nResolves audience and populates recipients.","operationId":"schedule_campaign_api_marketing_campaigns__campaign_id__schedule_post","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/send-now":{"post":{"tags":["Marketing"],"summary":"Send Campaign Now","description":"Send a campaign immediately (async — returns right away, sends in background).\n\nOptional body: ``{\"allow_default_sender\": true}`` to send a campaign that has\nno verified sending domain from the default sender instead of being blocked.","operationId":"send_campaign_now_api_marketing_campaigns__campaign_id__send_now_post","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/test-send":{"post":{"tags":["Marketing"],"summary":"Test Send Campaign","description":"Send a test email to a specific address. No credits deducted.","operationId":"test_send_campaign_api_marketing_campaigns__campaign_id__test_send_post","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/templates/test-send":{"post":{"tags":["Marketing"],"summary":"Test Send Template","description":"Send a test email with raw HTML content from template editor. No credits deducted.","operationId":"test_send_template_api_marketing_templates_test_send_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/vehicle-block/preview":{"post":{"tags":["Marketing"],"summary":"Preview Vehicle Block","description":"Live preview for the \"Inserir Viaturas\" dialog.\n\nTakes the same block config the editor encodes into the marker, resolves it\nthrough the exact send-time path (``parse_filter_spec`` + ``fetch_listings``),\nand returns how many vehicles currently match plus a small sample for thumbnails.\nRead-only — never sends anything, never deducts credits.","operationId":"preview_vehicle_block_api_marketing_vehicle_block_preview_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Cfg"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/cancel":{"post":{"tags":["Marketing"],"summary":"Cancel Campaign","description":"Cancel a scheduled campaign.","operationId":"cancel_campaign_api_marketing_campaigns__campaign_id__cancel_post","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/resume":{"post":{"tags":["Marketing"],"summary":"Resume Campaign","description":"Resume a failed/paused campaign, sending only to those still pending.","operationId":"resume_campaign_api_marketing_campaigns__campaign_id__resume_post","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/abort":{"post":{"tags":["Marketing"],"summary":"Abort Campaign","description":"Permanently end a failed/paused/sending campaign. Not reversible.","operationId":"abort_campaign_api_marketing_campaigns__campaign_id__abort_post","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/audience/preview":{"post":{"tags":["Marketing"],"summary":"Preview Audience Endpoint","description":"Preview audience based on filter criteria (count + sample + cost).","operationId":"preview_audience_endpoint_api_marketing_audience_preview_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/audience/sources":{"get":{"tags":["Marketing"],"summary":"Get Audience Sources","description":"Get available filter options (teams, brands, stages, POS).","operationId":"get_audience_sources_api_marketing_audience_sources_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/analytics":{"get":{"tags":["Marketing"],"summary":"Get Campaign Analytics","description":"Get campaign analytics (open/click/bounce rates).","operationId":"get_campaign_analytics_api_marketing_campaigns__campaign_id__analytics_get","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/history":{"get":{"tags":["Marketing"],"summary":"Get Campaign History Route","description":"Change history (HistoricoActions) for a campaign — who changed what, newest first.","operationId":"get_campaign_history_route_api_marketing_campaigns__campaign_id__history_get","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/campaigns/{campaign_id}/recipients":{"get":{"tags":["Marketing"],"summary":"Get Campaign Recipients","description":"Get paginated recipient list for a campaign.","operationId":"get_campaign_recipients_api_marketing_campaigns__campaign_id__recipients_get","parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"integer","title":"Campaign Id"}},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/unsubscribes":{"get":{"tags":["Marketing"],"summary":"List Unsubscribes","description":"List unsubscribed emails for company.","operationId":"list_unsubscribes_api_marketing_unsubscribes_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Marketing"],"summary":"Add Unsubscribe","description":"Manually add email to unsubscribe list.","operationId":"add_unsubscribe_api_marketing_unsubscribes_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/unsubscribes/{unsub_id}":{"delete":{"tags":["Marketing"],"summary":"Remove Unsubscribe","description":"Remove email from unsubscribe list.","operationId":"remove_unsubscribe_api_marketing_unsubscribes__unsub_id__delete","parameters":[{"name":"unsub_id","in":"path","required":true,"schema":{"type":"integer","title":"Unsub Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/recipient-search":{"get":{"tags":["Marketing"],"summary":"Search Recipients","description":"Search Z_ClientProspect + Cliente for a name/email/phone substring, tenant-scoped.\nExcludes already-unsubscribed emails. Used by the Cancelamentos picker.","operationId":"search_recipients_api_marketing_recipient_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":25,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/reputation":{"get":{"tags":["Marketing"],"summary":"Get Reputation","description":"Get company's sending reputation and suspension status.","operationId":"get_reputation_api_marketing_reputation_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/reputation/bounce-log":{"get":{"tags":["Marketing"],"summary":"Get Bounce Log","description":"Get bounce/complaint event log.","operationId":"get_bounce_log_api_marketing_reputation_bounce_log_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/reputation/unsuspend":{"post":{"tags":["Marketing"],"summary":"Unsuspend Company","description":"Manually unsuspend a company. Resets the legacy cumulative counters.\n\nGated on `admin`: this lifts a deliverability block that protects a SHARED\nSES account — one tenant mailing a dirty list can get sending throttled for\nevery company on the platform. Until now the only barrier was the\n`modulo.marketing` module gate, so any user who could open the Marketing tab\ncould clear their own company's suspension from the \"Reativar\" button.\nCompany-level management action, so `admin`, not `system_admin`.\n\nNOTE this does NOT reset the bounce rate. Rates come from a rolling 30-day\nwindow over Z_MarketingBounceLog (_REPUTATION_WINDOW_SQL); zeroing the\ncolumns no longer moves them. If the real rate is still above the threshold,\nthe next permanent bounce re-suspends. See unsuspend_company() in\napp/db/marketing.py — the remedy is to clean the list and let the window\nroll, not to press this again.","operationId":"unsuspend_company_api_marketing_reputation_unsuspend_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/reputation/daily-limit":{"put":{"tags":["Marketing"],"summary":"Set Daily Limit","description":"Set daily sending limit for the company.","operationId":"set_daily_limit_api_marketing_reputation_daily_limit_put","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/meta-catalog/info":{"get":{"tags":["Meta Catalog - Admin"],"summary":"Feed URLs + destinations for the catalog feed","description":"Everything the tab needs: one ready feed URL per public domain, plus the\ndestinations actually in use (so the user can append ?portal=...).","operationId":"meta_catalog_info_api_marketing_meta_catalog_info_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/meta-catalog/settings":{"post":{"tags":["Meta Catalog - Admin"],"summary":"Toggle enriched (marketing-card) feed images for the company","description":"Enable/disable generated marketing-card images in this company's feed.\nCards are produced out of band by the ``meta_card_generator`` cron; until one\nexists the feed shows the raw photo, so enabling is always safe.","operationId":"update_meta_catalog_settings_api_marketing_meta_catalog_settings_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_EnrichedImagesIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/meta-catalog/brand-settings":{"post":{"tags":["Meta Catalog - Admin"],"summary":"Override enriched feed images for a single brand (or clear the override)","description":"Per-brand override of the company default: ``true``/``false`` sets an explicit\nvalue for the brand, ``null`` clears it (revert to the company default). The\nbrand must belong to the caller's company.","operationId":"update_meta_catalog_brand_settings_api_marketing_meta_catalog_brand_settings_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_BrandEnrichedImagesIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marketing/meta-catalog/preview":{"get":{"tags":["Meta Catalog - Admin"],"summary":"Preview the Meta catalog feed for the current company","description":"Render a brand feed fresh (bypassing the 15-min cache) for an admin preview.","operationId":"preview_meta_catalog_api_marketing_meta_catalog_preview_get","parameters":[{"name":"portal","in":"query","required":false,"schema":{"type":"string","description":"Destination slug, or 'site'","title":"Portal"},"description":"Destination slug, or 'site'"},{"name":"domain","in":"query","required":false,"schema":{"type":"string","description":"Brand domain to preview; defaults to the primary website","title":"Domain"},"description":"Brand domain to preview; defaults to the primary website"},{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"'vehicles' (AIA) or 'products' (Google-Merchant)","default":"vehicles","title":"Format"},"description":"'vehicles' (AIA) or 'products' (Google-Merchant)"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/redirect-links":{"get":{"tags":["Redirect Links - Protected"],"summary":"List Redirect Links","description":"List all redirect links for a website.","operationId":"list_redirect_links_api_redirect_links_get","parameters":[{"name":"website_id","in":"query","required":true,"schema":{"type":"integer","description":"Website ID","title":"Website Id"},"description":"Website ID"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Redirect Links - Protected"],"summary":"Create Redirect Link Route","description":"Create a new redirect link.\nReturns 409 if slug already exists for this website.","operationId":"create_redirect_link_route_api_redirect_links_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/redirect-links/{link_id}":{"get":{"tags":["Redirect Links - Protected"],"summary":"Get Redirect Link","description":"Get a single redirect link by ID.","operationId":"get_redirect_link_api_redirect_links__link_id__get","parameters":[{"name":"link_id","in":"path","required":true,"schema":{"type":"integer","title":"Link Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Redirect Links - Protected"],"summary":"Update Redirect Link Route","description":"Update an existing redirect link.","operationId":"update_redirect_link_route_api_redirect_links__link_id__put","parameters":[{"name":"link_id","in":"path","required":true,"schema":{"type":"integer","title":"Link Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Redirect Links - Protected"],"summary":"Delete Redirect Link Route","description":"Delete a redirect link.","operationId":"delete_redirect_link_route_api_redirect_links__link_id__delete","parameters":[{"name":"link_id","in":"path","required":true,"schema":{"type":"integer","title":"Link Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/templates":{"get":{"tags":["Checkups"],"summary":"List Templates","description":"List active templates (company-specific + system defaults).","operationId":"list_templates_api_checkups_templates_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Checkups"],"summary":"Create Template","description":"Create a new company-specific template.\n\nBody: name (str), sections (array), description (str, optional), is_default (bool, optional)","operationId":"create_template_api_checkups_templates_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/templates/{template_id}":{"get":{"tags":["Checkups"],"summary":"Get Template","description":"Get a single template with full sections JSON.","operationId":"get_template_api_checkups_templates__template_id__get","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Checkups"],"summary":"Update Template","description":"Update a company-specific template. Cannot edit system defaults.","operationId":"update_template_api_checkups_templates__template_id__put","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Checkups"],"summary":"Delete Template","description":"Soft-delete a company-specific template. Cannot delete system defaults.","operationId":"delete_template_api_checkups_templates__template_id__delete","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/templates/{template_id}/set-default":{"put":{"tags":["Checkups"],"summary":"Set Default Template","description":"Set a template as the company default.","operationId":"set_default_template_api_checkups_templates__template_id__set_default_put","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"integer","title":"Template Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/sessions":{"post":{"tags":["Checkups"],"summary":"Create Session","description":"Create a new check-up session.\n\nBody: vehicle_id (int), template_id (int), entry_photo_urls (array of strings, min 1),\n      performed_by (int, optional)","operationId":"create_session_api_checkups_sessions_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/sessions/{session_id}":{"get":{"tags":["Checkups"],"summary":"Get Session","description":"Get a session with full answers, photos, and template info.","operationId":"get_session_api_checkups_sessions__session_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Checkups"],"summary":"Update Session","description":"Update a draft session.\n\nBody: answers (object, optional), header_data (object, optional),\n      notes (str, optional), performed_by (int, optional)","operationId":"update_session_api_checkups_sessions__session_id__put","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/sessions/{session_id}/conclude":{"put":{"tags":["Checkups"],"summary":"Conclude Session","description":"Conclude a session. After this, it becomes immutable.","operationId":"conclude_session_api_checkups_sessions__session_id__conclude_put","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/sessions/{session_id}/resolve-field":{"put":{"tags":["Checkups"],"summary":"Resolve Field","description":"Add or update a resolution for a 'Não' field on a concluded session.","operationId":"resolve_field_api_checkups_sessions__session_id__resolve_field_put","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/sessions/{session_id}/pdf":{"get":{"tags":["Checkups"],"summary":"Export Session Pdf","description":"Export a concluded checkup session as a PDF persisted in Documentos.\nReturns the Documentos.ID so the frontend can open it in DocumentViewDialog.\nRegenerates the PDF on every call (so resolutions are always reflected);\nif a Documentos row already exists for this session, its file pointer is\noverwritten in place.","operationId":"export_session_pdf_api_checkups_sessions__session_id__pdf_get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/vehicles/{vehicle_id}/active":{"get":{"tags":["Checkups"],"summary":"Get Active Sessions","description":"Get all active draft check-up sessions for a vehicle.","operationId":"get_active_sessions_api_checkups_vehicles__vehicle_id__active_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/vehicles/{vehicle_id}/history":{"get":{"tags":["Checkups"],"summary":"Get Vehicle History","description":"Get check-up history for a vehicle (all sessions, paginated).","operationId":"get_vehicle_history_api_checkups_vehicles__vehicle_id__history_get","parameters":[{"name":"vehicle_id","in":"path","required":true,"schema":{"type":"integer","title":"Vehicle Id"}},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/upload-photo":{"post":{"tags":["Checkups"],"summary":"Upload Photo","description":"Upload a single photo to S3 (checkups folder). Returns the S3 URL.\nNo DB record created yet — used before session creation (entry photos)\nor to get URLs before calling POST /sessions/{id}/photos.","operationId":"upload_photo_api_checkups_upload_photo_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_photo_api_checkups_upload_photo_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/sessions/{session_id}/photos":{"post":{"tags":["Checkups"],"summary":"Add Session Photos","description":"Add photos to a session.\n\nBody: urls (array of strings), photo_type ('entry' | 'field'), field_key (str, optional)","operationId":"add_session_photos_api_checkups_sessions__session_id__photos_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Checkups"],"summary":"List Session Photos","description":"List all photos for a session, grouped by type.","operationId":"list_session_photos_api_checkups_sessions__session_id__photos_get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/sessions/{session_id}/photos/{photo_id}":{"delete":{"tags":["Checkups"],"summary":"Delete Session Photo","description":"Delete a photo. Concluded sessions only allow deleting resolution photos. Also removes from S3.","operationId":"delete_session_photo_api_checkups_sessions__session_id__photos__photo_id__delete","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"photo_id","in":"path","required":true,"schema":{"type":"integer","title":"Photo Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkups/sessions/{session_id}/photos/download-urls":{"post":{"tags":["Checkups"],"summary":"Get Photo Download Urls","description":"Generate presigned S3 URLs with Content-Disposition: attachment for downloading.\n\nBody: urls (array of bucket_url strings)\nReturns: array of { original_url, download_url, filename }","operationId":"get_photo_download_urls_api_checkups_sessions__session_id__photos_download_urls_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/financial/summary":{"get":{"tags":["Reports"],"summary":"Get Financial Summary","description":"Get financial overview totals: lucros carros, lucros outros,\ndespesas, IVA liquidado, IVA deduzido, and computed totals.","operationId":"get_financial_summary_api_reports_financial_summary_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Month(s) to include (1-12)","default":[],"title":"Mes"},"description":"Month(s) to include (1-12)"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/financial/lucros-carros/detail":{"get":{"tags":["Reports"],"summary":"Get Lucros Carros Detail","description":"Lucros Carros per-vehicle breakdown.","operationId":"get_lucros_carros_detail_api_reports_financial_lucros_carros_detail_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Month(s) to include (1-12)","default":[],"title":"Mes"},"description":"Month(s) to include (1-12)"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/financial/outros-lucros/detail":{"get":{"tags":["Reports"],"summary":"Get Outros Lucros Detail","description":"Outros Lucros per-movement breakdown with rubrica summary.","operationId":"get_outros_lucros_detail_api_reports_financial_outros_lucros_detail_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Month(s) to include (1-12)","default":[],"title":"Mes"},"description":"Month(s) to include (1-12)"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/financial/iva-deduzido/detail":{"get":{"tags":["Reports"],"summary":"Get Iva Deduzido Detail","description":"IVA Deduzido per-invoice breakdown.","operationId":"get_iva_deduzido_detail_api_reports_financial_iva_deduzido_detail_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Month(s) to include (1-12)","default":[],"title":"Mes"},"description":"Month(s) to include (1-12)"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/financial/despesas/detail":{"get":{"tags":["Reports"],"summary":"Get Despesas Detail","description":"Despesas per-movement breakdown with rubrica summary.","operationId":"get_despesas_detail_api_reports_financial_despesas_detail_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Month(s) to include (1-12)","default":[],"title":"Mes"},"description":"Month(s) to include (1-12)"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/financial/iva-liquidado/detail":{"get":{"tags":["Reports"],"summary":"Get Iva Liquidado Detail","description":"IVA Liquidado per-contract breakdown.","operationId":"get_iva_liquidado_detail_api_reports_financial_iva_liquidado_detail_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Month(s) to include (1-12)","default":[],"title":"Mes"},"description":"Month(s) to include (1-12)"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/inventory/detail":{"get":{"tags":["Reports"],"summary":"Get Inventory Detail","description":"Get inventory detail for a given month/year.\n\nReturns vehicles in stock at end of month with purchase values\nand invoice status.","operationId":"get_inventory_detail_api_reports_inventory_detail_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Month(s) to include; uses max month as end-of-period cutoff","default":[],"title":"Mes"},"description":"Month(s) to include; uses max month as end-of-period cutoff"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"consignado","in":"query","required":true,"schema":{"type":"integer","maximum":1,"minimum":0,"title":"Consignado"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/inventory/summary":{"get":{"tags":["Reports"],"summary":"Get Inventory Summary","description":"Get inventory summary totals for own and consigned vehicles.\n\nReturns total value and missing invoice count for each type.","operationId":"get_inventory_summary_api_reports_inventory_summary_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Month(s) to include; uses max month as end-of-period cutoff","default":[],"title":"Mes"},"description":"Month(s) to include; uses max month as end-of-period cutoff"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/inventory/trend":{"get":{"tags":["Reports"],"summary":"Get Inventory Trend","description":"Get monthly inventory value trend for the year up to the given month.\n\nReturns array of {AnalysisDate, own_total, consigned_total} per month.","operationId":"get_inventory_trend_api_reports_inventory_trend_get","parameters":[{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Month(s); uses max month as upper bound for trend","default":[],"title":"Mes"},"description":"Month(s); uses max month as upper bound for trend"},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/inventory/costs":{"get":{"tags":["Reports"],"summary":"Get Inventory Costs","description":"Inventário com custos: the vehicles in stock at the end of the period,\neach with EVERY cost movement (purchase + expenses, one row per movement\nwith its own invoice reference) and a server-computed subtotal — the JSON\ntwin of the monthly email's \"Custos\" sheet\n(inventory_report.flatten_inventory_costs is the shared core).\n\nSingle as-of period: the cutoff is end of max(mes) of `ano`. Do NOT fan\nthis out per year and merge client-side — movements carry only an UPPER\ndate bound, so responses for different years overlap and a merge\ndouble-counts every euro. Totals come computed from here; the FE renders\nthem and must not re-sum floats in JS.\nNOT cached — same reasoning as /detail (see the top of this file), and\nthis response is strictly larger.","operationId":"get_inventory_costs_api_reports_inventory_costs_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Month(s); uses max month as end-of-period cutoff","default":[],"title":"Mes"},"description":"Month(s); uses max month as end-of-period cutoff"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"consignado","in":"query","required":true,"schema":{"type":"integer","maximum":1,"minimum":0,"title":"Consignado"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/inventory/costs/summary":{"get":{"tags":["Reports"],"summary":"Get Inventory Costs Summary","description":"Headline cost figures for both own and consigned stock — what the Stock\ncard shows once the user flips it to \"com custos\": vehicle count, total\ncost, and the purchase/expense split.\n\nSame assembly as /inventory/costs, so the card and the dialog it opens\nalways agree. Cacheable (unlike /costs itself) because the response is a\nhandful of numbers, not the row set — same class as /inventory/summary.\nThe FE only calls it when a card enters costs mode, so the underlying\nqueries stay off the default dashboard load.","operationId":"get_inventory_costs_summary_api_reports_inventory_costs_summary_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Month(s); uses max month as end-of-period cutoff","default":[],"title":"Mes"},"description":"Month(s); uses max month as end-of-period cutoff"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/inventory/costs/export":{"get":{"tags":["Reports"],"summary":"Export Inventory Costs","description":"Styled .xlsx download of the costs view — rendered by the SAME code as\nthe emailed monthly report's \"Custos\" sheet (shaded per-vehicle subtotals,\ngrand TOTAL, currency/date formats), so the export can never drift from\nthe email. Same single-as-of-period contract as /inventory/costs.","operationId":"export_inventory_costs_api_reports_inventory_costs_export_get","parameters":[{"name":"mes","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer","maximum":12,"minimum":1},"description":"Month(s); uses max month as end-of-period cutoff","default":[],"title":"Mes"},"description":"Month(s); uses max month as end-of-period cutoff"},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"consignado","in":"query","required":true,"schema":{"type":"integer","maximum":1,"minimum":0,"title":"Consignado"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/socios/monthly-statement":{"get":{"tags":["Reports"],"summary":"Get Socios Monthly Statement","description":"Per-sócio monthly P&L statement.\n\nReturns one entry per sócio:\n- `valor_mes` — share for the target month\n- `valor_acumulado` — cumulative shares from `(start_ano, start_mes)` to\n  `(ano, mes)` PLUS `Z_Partners.valor_inicial`\n- `total_withdrawn` — sign-aware sum of `MovimentosSocios`-linked\n  movements up to `(ano, mes)`; withdrawals are typically negative\n- `total_available = valor_acumulado + total_withdrawn`\n- `by_pv` — per-PV breakdown of the same four values\n\nPercentage normalization stays per-PV (active sócios' percentages sum to\nthe divisor, not 100). Closed-vehicle movements paid before `datafecho`\nare re-attributed to the closure month at the closure PV. Both rules\nmatch the legacy `get_socio_report_complete_month` semantics.","operationId":"get_socios_monthly_statement_api_reports_socios_monthly_statement_get","parameters":[{"name":"mes","in":"query","required":true,"schema":{"type":"integer","maximum":12,"minimum":1,"title":"Mes"}},{"name":"ano","in":"query","required":true,"schema":{"type":"integer","maximum":2100,"minimum":2000,"title":"Ano"}},{"name":"partner_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Partner Id"}},{"name":"ponto_venda_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Ponto Venda Id"}},{"name":"start_ano","in":"query","required":false,"schema":{"type":"integer","maximum":2100,"minimum":2000,"description":"Cumulative window start year","default":2023,"title":"Start Ano"},"description":"Cumulative window start year"},{"name":"start_mes","in":"query","required":false,"schema":{"type":"integer","maximum":12,"minimum":1,"description":"Cumulative window start month","default":1,"title":"Start Mes"},"description":"Cumulative window start month"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/oficina/reports/kpi":{"get":{"tags":["Oficina Reports"],"summary":"Get Kpi","description":"Live KPI snapshot: vehicles in parque / transporte / preparação /\nprontos / bloqueados. Ignores the date range (always current state).\n\nShares `get_logistics_kpi()` with `/logistica/kpi` — single source of\ntruth for the five bucket definitions. Estado=5 (Suspenso) is always\nexcluded regardless of the `estado_id` filter.","operationId":"get_kpi_api_oficina_reports_kpi_get","parameters":[{"name":"pv_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Pv Id"}},{"name":"estado_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Sales-state filter: 2=Em Stock, 3=Reservado, 4=Vendido. Empty = all non-Suspenso.","default":[],"title":"Estado Id"},"description":"Sales-state filter: 2=Em Stock, 3=Reservado, 4=Vendido. Empty = all non-Suspenso."},{"name":"park_location_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Filter by one or more Z_ParkLocations.id (Viatura.current_park_location_id).","default":[],"title":"Park Location Id"},"description":"Filter by one or more Z_ParkLocations.id (Viatura.current_park_location_id)."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/oficina/reports/preparacao":{"get":{"tags":["Oficina Reports"],"summary":"Get Preparacao","description":"Preparation duration analytics: avg/median/P90, buckets, trend, aging list.","operationId":"get_preparacao_api_oficina_reports_preparacao_get","parameters":[{"name":"pv_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Pv Id"}},{"name":"estado_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Estado Id"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}},{"name":"aging_threshold_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":7,"title":"Aging Threshold Days"}},{"name":"park_location_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Park Location Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Selected year for month-over-month trend.","title":"Year"},"description":"Selected year for month-over-month trend."},{"name":"month","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Selected month(s); a single month enables the trend badge.","default":[],"title":"Month"},"description":"Selected month(s); a single month enables the trend badge."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/oficina/reports/prontidao":{"get":{"tags":["Oficina Reports"],"summary":"Get Prontidao","description":"Commercial-readiness analytics focused on pronto_entrega_data.","operationId":"get_prontidao_api_oficina_reports_prontidao_get","parameters":[{"name":"pv_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Pv Id"}},{"name":"estado_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Estado Id"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}},{"name":"aging_threshold_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Aging Threshold Days"}},{"name":"park_location_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Park Location Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Selected year for month-over-month trend.","title":"Year"},"description":"Selected year for month-over-month trend."},{"name":"month","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Selected month(s); a single month enables the trend badge.","default":[],"title":"Month"},"description":"Selected month(s); a single month enables the trend badge."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/oficina/reports/transportes":{"get":{"tags":["Oficina Reports"],"summary":"Get Transportes","description":"Transport duration, on-time %, overdue, monthly volume, top routes.","operationId":"get_transportes_api_oficina_reports_transportes_get","parameters":[{"name":"pv_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Pv Id"}},{"name":"estado_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Estado Id"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}},{"name":"park_location_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Filter by destino_park_id (transports going to one or more of these parks).","default":[],"title":"Park Location Id"},"description":"Filter by destino_park_id (transports going to one or more of these parks)."},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Selected year for month-over-month trend.","title":"Year"},"description":"Selected year for month-over-month trend."},{"name":"month","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Selected month(s); a single month enables the trend badge.","default":[],"title":"Month"},"description":"Selected month(s); a single month enables the trend badge."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/oficina/reports/ciclo-vida":{"get":{"tags":["Oficina Reports"],"summary":"Get Ciclo Vida","description":"Lifecycle funnel averages: chegada → prep_inicio → prep_fim, per-PV.","operationId":"get_ciclo_vida_api_oficina_reports_ciclo_vida_get","parameters":[{"name":"pv_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Pv Id"}},{"name":"estado_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Estado Id"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}},{"name":"park_location_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Park Location Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/oficina/reports/bloqueios":{"get":{"tags":["Oficina Reports"],"summary":"Get Bloqueios","description":"Sale-block analytics: active, avg closed duration, longest, monthly trend.","operationId":"get_bloqueios_api_oficina_reports_bloqueios_get","parameters":[{"name":"pv_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Pv Id"}},{"name":"estado_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Estado Id"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}},{"name":"park_location_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"default":[],"title":"Park Location Id"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Selected year for month-over-month trend.","title":"Year"},"description":"Selected year for month-over-month trend."},{"name":"month","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Selected month(s); a single month enables the trend badge.","default":[],"title":"Month"},"description":"Selected month(s); a single month enables the trend badge."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/registrations/":{"post":{"tags":["Company Registration - Admin"],"summary":"Create a registration and onboard the company","description":"Admin-side conversion of a lead into a real company. Creates the\nZ_CompanyRegistrations row (the durable record), validates an optional\npromo code → parent PV, then runs the full onboarding immediately\n(company + PV + clients + invite) and marks the registration approved.\n\nThe referral, if a code was given, materializes later when the new\ncompany's owner finishes onboarding (/onboarding/complete reads the\nregistration's promo_code via resulting_company_id) — same chain the\npublic registration uses.","operationId":"admin_create_registration_api_admin_registrations__post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreateRegistrationRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Company Registration - Admin"],"summary":"List registrations","description":"List all company registrations, filterable by status.","operationId":"list_registrations_api_admin_registrations__get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/registrations/plans":{"get":{"tags":["Company Registration - Admin"],"summary":"List available plans","description":"List all active plans for the plan selection dropdown.","operationId":"list_plans_api_admin_registrations_plans_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/registrations/leads":{"get":{"tags":["Company Registration - Admin"],"summary":"Recent inbound leads (for lead → registration conversion)","description":"List recent inbound leads for the StandGest company (default id 17) so an\nadmin can convert one into a company registration. The public /registar\nform lands here as a Z_Leads row; this surfaces the prospect's name, email,\nphone and any referral promo_code captured in the lead's data JSON, ready to\nprefill the \"Criar Registo\" dialog.","operationId":"list_conversion_leads_api_admin_registrations_leads_get","parameters":[{"name":"company_id","in":"query","required":false,"schema":{"type":"integer","description":"Company whose inbound leads to list (StandGest's own company by default)","default":17,"title":"Company Id"},"description":"Company whose inbound leads to list (StandGest's own company by default)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by name / email / phone substring","title":"Search"},"description":"Filter by name / email / phone substring"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/registrations/{registration_id}":{"get":{"tags":["Company Registration - Admin"],"summary":"Get registration details","description":"Get registration details with presigned URL for CAE document.","operationId":"get_registration_api_admin_registrations__registration_id__get","parameters":[{"name":"registration_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Registration Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Company Registration - Admin"],"summary":"Edit registration before approval","description":"Edit registration fields before approval.\nOnly works on registrations with status 'pending_review'.\nAllowed fields: company_name, nipc, personal_name, personal_email.","operationId":"edit_registration_api_admin_registrations__registration_id__put","parameters":[{"name":"registration_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Registration Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/registrations/{registration_id}/approve":{"post":{"tags":["Company Registration - Admin"],"summary":"Approve registration","description":"Approve a registration and trigger full company onboarding.\nCreates company, PV, clients, plan subscription, and user invitation.\nOptionally accepts plan_id to select a specific plan (defaults to Free).","operationId":"approve_registration_api_admin_registrations__registration_id__approve_post","parameters":[{"name":"registration_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Registration Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/registrations/{registration_id}/deny":{"post":{"tags":["Company Registration - Admin"],"summary":"Deny registration","description":"Deny a registration with a reason.\nSends a denial email to the applicant.","operationId":"deny_registration_api_admin_registrations__registration_id__deny_post","parameters":[{"name":"registration_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Registration Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/registrations/{registration_id}/retry-invitation":{"post":{"tags":["Company Registration - Admin"],"summary":"Retry user invitation","description":"Retry the user invitation for an approved registration\nwhere the initial invitation failed (no active users created).","operationId":"retry_invitation_api_admin_registrations__registration_id__retry_invitation_post","parameters":[{"name":"registration_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Registration Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/onboarding/progress":{"get":{"tags":["Onboarding"],"summary":"Get onboarding progress","description":"Returns onboarding progress for the authenticated user's company.\nIncludes completion percentage, step statuses, and whether onboarding can be completed.","operationId":"get_onboarding_progress_api_onboarding_progress_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Onboarding Progress Api Onboarding Progress Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/onboarding/complete":{"post":{"tags":["Onboarding"],"summary":"Complete onboarding","description":"Complete onboarding and transition company to 'active' status.\nValidates that all mandatory steps are completed (payment methods configured).","operationId":"complete_onboarding_api_onboarding_complete_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Complete Onboarding Api Onboarding Complete Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/onboarding/pvs":{"post":{"tags":["Onboarding"],"summary":"Create a new PV during onboarding wizard","description":"Simplified PV creation for the onboarding wizard.\nAuto-assigns the company's current plan. Only requires DESIGANCAO.","operationId":"create_wizard_pv_api_onboarding_pvs_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizardPVCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/onboarding/pvs/{pv_id}":{"delete":{"tags":["Onboarding"],"summary":"Delete a wizard-created PV","description":"Delete a PV created during the onboarding wizard.\nGuards: cannot delete the original (first) PV, cannot delete if users are assigned.","operationId":"delete_wizard_pv_api_onboarding_pvs__pv_id__delete","parameters":[{"name":"pv_id","in":"path","required":true,"schema":{"type":"integer","title":"Pv Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/onboarding/feature-readiness":{"get":{"tags":["Onboarding"],"summary":"Get feature readiness status","description":"Returns readiness status for all features that depend on setup data.\nEach feature includes a 'ready' flag and a list of missing prerequisites.\nUsed by the frontend for feature gates and the Settings setup card.","operationId":"get_feature_readiness_api_onboarding_feature_readiness_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Feature Readiness Api Onboarding Feature Readiness Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/onboarding/setup-completion":{"get":{"tags":["Onboarding"],"summary":"Get post-onboarding setup completion","description":"Returns setup completion checks for the dashboard banner.\nThese are genuinely optional post-onboarding items (logo, IBAN, phone, vehicles, team).","operationId":"get_setup_completion_api_onboarding_setup_completion_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Setup Completion Api Onboarding Setup Completion Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires":{"post":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Issue an onboarding questionnaire link","description":"Create a questionnaire for a company and email the link to the dealer.\n\nThe raw link is returned HERE AND ONLY HERE — the token is stored hashed, so\nit can never be shown again. The UI must present it for copying now; after\nthat, the only way to hand it over is a resend, which rotates it.","operationId":"create_link_api_admin_onboarding_questionnaires_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLinkRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Onboarding Questionnaire - Admin"],"summary":"List questionnaires","operationId":"list_questionnaires_api_admin_onboarding_questionnaires_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Include Inactive"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}/resend-link":{"post":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Rotate and resend the link","operationId":"resend_link_api_admin_onboarding_questionnaires__questionnaire_id__resend_link_post","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}/revoke-link":{"post":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Kill the link","operationId":"revoke_link_api_admin_onboarding_questionnaires__questionnaire_id__revoke_link_post","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}":{"get":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Full questionnaire detail","description":"Everything the review screen needs, in one call.\n\n`token_hash` is stripped: it is a credential digest and the reviewer has no\nuse for it. Uploads come back as metadata only — the presigned URL is minted\non demand by the dedicated endpoint, so a long-lived link never sits in a\ncached JSON payload.","operationId":"get_questionnaire_api_admin_onboarding_questionnaires__questionnaire_id__get","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}/uploads/{upload_id}":{"get":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Presigned download for an uploaded file","description":"Mint a short-lived download URL.\n\nScoped to the questionnaire, never fetched by upload id alone — otherwise a\ntampered path would hand back another questionnaire's file.\n\n`inline=False`: these are client-supplied files sitting in the bucket shared\nwith contracts and client documents. They are downloaded, never rendered on\nthe bucket origin.","operationId":"get_upload_url_api_admin_onboarding_questionnaires__questionnaire_id__uploads__upload_id__get","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"upload_id","in":"path","required":true,"schema":{"type":"integer","title":"Upload Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}/start-review":{"post":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Take the questionnaire into review","operationId":"start_review_api_admin_onboarding_questionnaires__questionnaire_id__start_review_post","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}/reopen":{"post":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Send back to the client for corrections","description":"Reopen for editing and email the client a fresh link.\n\nRefused while any section is mid-apply — see the service for why.","operationId":"reopen_api_admin_onboarding_questionnaires__questionnaire_id__reopen_post","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}/close":{"post":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Close the questionnaire","description":"Finish with a questionnaire: frees the company's slot and kills the link.\n\nClosing does NOT require every section to be applied. In stage 1 no section\nCAN be applied (there is no apply layer yet), so demanding terminal sections\nwould leave `cancel` as the only exit and a company could never be issued a\nsecond questionnaire. The outcome records which case this was.","operationId":"close_api_admin_onboarding_questionnaires__questionnaire_id__close_post","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}/cancel":{"post":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Cancel the questionnaire","description":"Abandon a questionnaire at any stage. Frees the one-active-per-company\nslot so a fresh link can be issued.","operationId":"cancel_api_admin_onboarding_questionnaires__questionnaire_id__cancel_post","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}/sections/{section_key}/skip":{"post":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Mark a section as deliberately not applied","operationId":"skip_section_api_admin_onboarding_questionnaires__questionnaire_id__sections__section_key__skip_post","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"section_key","in":"path","required":true,"schema":{"type":"string","title":"Section Key"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/onboarding-questionnaires/{questionnaire_id}/sections/{section_key}/ack":{"post":{"tags":["Onboarding Questionnaire - Admin"],"summary":"Acknowledge a record-only section","description":"For sections with no apply target (sócios, stack, marketing, perfil do\nnegócio): the reviewer confirms they have read and actioned them outside the\nplatform. The answers stay on the questionnaire and the ticket.","operationId":"ack_section_api_admin_onboarding_questionnaires__questionnaire_id__sections__section_key__ack_post","parameters":[{"name":"questionnaire_id","in":"path","required":true,"schema":{"type":"integer","title":"Questionnaire Id"}},{"name":"section_key","in":"path","required":true,"schema":{"type":"string","title":"Section Key"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referrals/code":{"get":{"tags":["Referrals"],"summary":"Get the caller PV's shareable referral code","description":"Return the authenticated PV's own promo code (the one it shares to refer friend\ncompanies). Provisions a code on the fly if the PV somehow has none yet.","operationId":"get_my_referral_code_api_referrals_code_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referrals/share-image":{"get":{"tags":["Referrals"],"summary":"Generate the caller PV's shareable referral image","description":"Render (or refresh) the PV's referral share PNG and return a presigned URL to\nit. The image embeds the PV's code, company logo/branding, and a QR to the\nprefilled signup page.","operationId":"get_referral_share_image_api_referrals_share_image_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referrals/status":{"get":{"tags":["Referrals"],"summary":"Parent-side referral status for the company","description":"Referral status for the caller's company as a referrer: how many PVs it has\nreferred, accrued commission within the current windows, and the per-referral\nwindow state + days remaining.","operationId":"get_referral_status_api_referrals_status_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-analysis/analyze/{call_id}":{"post":{"tags":["Call Analysis"],"summary":"Analyze Call Endpoint","description":"Manually trigger AI analysis for a specific call (async).","operationId":"analyze_call_endpoint_api_call_analysis_analyze__call_id__post","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"integer","title":"Call Id"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Force full re-analysis from scratch","default":false,"title":"Force"},"description":"Force full re-analysis from scratch"},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-analysis/config":{"get":{"tags":["Call Analysis"],"summary":"Get Config","description":"Get AI call analysis configuration for the company.","operationId":"get_config_api_call_analysis_config_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Call Analysis"],"summary":"Update Config","description":"Update AI call analysis configuration for the company.","operationId":"update_config_api_call_analysis_config_put","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-analysis/list":{"get":{"tags":["Call Analysis"],"summary":"List Analyses","description":"List call analyses for the company.","operationId":"list_analyses_api_call_analysis_list_get","parameters":[{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by user ID","title":"User Id"},"description":"Filter by user ID"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-analysis/performance":{"get":{"tags":["Call Analysis"],"summary":"List Performances","description":"Get all users' sales performance for the company.","operationId":"list_performances_api_call_analysis_performance_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-analysis/performance/{user_id}":{"get":{"tags":["Call Analysis"],"summary":"Get Performance","description":"Get a user's sales performance summary.","operationId":"get_performance_api_call_analysis_performance__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-analysis/{call_id}":{"get":{"tags":["Call Analysis"],"summary":"Get Analysis","description":"Get analysis results for a specific call.","operationId":"get_analysis_api_call_analysis__call_id__get","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"integer","title":"Call Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/call-analysis/performance/{user_id}/narrative":{"post":{"tags":["Call Analysis"],"summary":"Generate Narrative","description":"Generate an AI narrative for a user's performance (on-demand).","operationId":"generate_narrative_api_call_analysis_performance__user_id__narrative_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/signatures/initiate":{"post":{"tags":["Signatures"],"summary":"Initiate Signature","description":"Start a CMD digital signature session.\n\nBody: {\n    document_type: \"contract\" | \"proposal\" | \"declaration\",\n    document_id: 123,\n    signer_type: \"client\" | \"commercial\",\n    signer_phone: \"+351912345678\",\n    signer_pin: \"1234\",\n    signer_name: \"João Silva\" (optional),\n    pdf_s3_key: \"path/to/existing.pdf\" (optional — if PDF already exists)\n}","operationId":"initiate_signature_api_signatures_initiate_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/signatures/{session_id}/validate-otp":{"post":{"tags":["Signatures"],"summary":"Validate Otp","description":"Complete signature by validating the OTP code.\nBody: { otp: \"123456\" }","operationId":"validate_otp_api_signatures__session_id__validate_otp_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/signatures/{session_id}/resend-otp":{"post":{"tags":["Signatures"],"summary":"Resend Otp","description":"Resend OTP for an existing signature session.","operationId":"resend_otp_api_signatures__session_id__resend_otp_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/signatures/{session_id}":{"get":{"tags":["Signatures"],"summary":"Get Session","description":"Get signature session status.","operationId":"get_session_api_signatures__session_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/signatures/document/{document_type}/{document_id}":{"get":{"tags":["Signatures"],"summary":"List Document Signatures","description":"List all signature sessions for a specific document.","operationId":"list_document_signatures_api_signatures_document__document_type___document_id__get","parameters":[{"name":"document_type","in":"path","required":true,"schema":{"type":"string","title":"Document Type"}},{"name":"document_id","in":"path","required":true,"schema":{"type":"integer","title":"Document Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/signatures/{session_id}/download":{"get":{"tags":["Signatures"],"summary":"Download Signed Pdf","description":"Get a presigned download URL for the signed PDF.","operationId":"download_signed_pdf_api_signatures__session_id__download_get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"integer","title":"Session Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assistant/chat":{"post":{"tags":["Assistant"],"summary":"Chat","description":"Send a message and receive a streaming response.\n\nBody:\n{\n    \"message\": \"como publico nos portais?\",\n    \"context\": {\n        \"currentRoute\": \"/vehicle/123/data\",\n        \"visibleButtons\": [\"Publicar Anúncio\", \"Editar\"],\n        \"page_data\": {\n            \"vehicle_id\": 123,\n            \"matricula\": \"AA-00-BB\",\n            \"marca\": \"BMW\",\n            \"modelo\": \"320d\",\n            \"estado\": \"Stock\"\n        }\n    }\n}\n\nReturns SSE stream:\n    data: {\"type\": \"token\", \"text\": \"Para\"}\n    ...\n    data: [DONE]","operationId":"chat_api_assistant_chat_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assistant/clear":{"post":{"tags":["Assistant"],"summary":"Clear History","description":"Clear conversation history.","operationId":"clear_history_api_assistant_clear_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assistant/history":{"get":{"tags":["Assistant"],"summary":"Get History","description":"Get conversation history.","operationId":"get_history_api_assistant_history_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-broadcast":{"get":{"tags":["System Broadcast"],"summary":"Get System Broadcast","description":"Return the active update warning, or {\"active\": null}. Any authenticated user.\n\nFiltered through _public_view() — no operator email, no internal uid.","operationId":"get_system_broadcast_api_system_broadcast_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["System Broadcast"],"summary":"Set System Broadcast","description":"Set the platform-wide update warning. system_admin only.\n\nThe message is rendered to every logged-in user across all tenants, so it is\nHTML-stripped (XSS convention) before storage; the frontend renders it as\nplain text.","operationId":"set_system_broadcast_api_system_broadcast_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWarningCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["System Broadcast"],"summary":"Clear System Broadcast","description":"Retract the active update warning. system_admin only.\n\nRetracts on BOTH surfaces: drops the banner and takes the announcement off\n/avisos. Clearing only the Redis key would leave a withdrawn message\nreadable by every user of every tenant indefinitely while the UI says it is\ngone. (The per-worker startup auto-clear in app/main.py stays cache-only —\nit fires 5x per deploy and must not touch the archive.)","operationId":"clear_system_broadcast_api_system_broadcast_delete","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/system-broadcast/history":{"get":{"tags":["System Broadcast"],"summary":"Get System Broadcast History","description":"Past \"Informação\" announcements, newest first. Any authenticated user.\n\nThe archive is platform-wide, so there is no company parameter and nothing\nto scope — see app/db/system_broadcasts.py.\n\nOperator identity (`created_by` / `created_by_label`) is stored but\ndeliberately NOT serialized here. Today it only ever appears in the\nsystem_admin-only POST response and in a Z_APIAuditLog row that\nplatform_paths.py hides from tenants; publishing it to every authenticated\nuser of every tenant would quietly undo that (docs/claude/02-security.md §10).\n\nPaging is keyset on the (sent_at, id) TUPLE — pass both cursor values back\nfrom `next_cursor`, or neither.","operationId":"get_system_broadcast_history_api_system_broadcast_history_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}},{"name":"before_sent_at","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Before Sent At"}},{"name":"before_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Before Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/unread-count":{"get":{"tags":["Notes"],"summary":"Badge count of unread shared notes","description":"Shares addressed to me that I have not opened yet.\n\nSoft on a session without a person (API token): the drawer is not reachable\nthere anyway, and a 403 would surface as a console error on every poll.","operationId":"unread_count_api_notes_unread_count_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes":{"get":{"tags":["Notes"],"summary":"List notes visible to the caller","operationId":"list_notes_api_notes_get","parameters":[{"name":"scope","in":"query","required":false,"schema":{"type":"string","pattern":"^(mine|shared|all)$","default":"all","title":"Scope"}},{"name":"done","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Done"}},{"name":"archived","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Archived"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Q"}},{"name":"id_modulo","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Modulo"}},{"name":"id_modulo_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Modulo Id"}},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Notes"],"summary":"Create a note","description":"Note + shares + the author's reminder, in one transaction.\n\nThe `note_shared` fan-out happens only AFTER the commit, and targets exactly\nthe recipient set the DB actually inserted.","operationId":"create_note_api_notes_post","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/{note_id}":{"get":{"tags":["Notes"],"summary":"Note detail","operationId":"get_note_api_notes__note_id__get","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Notes"],"summary":"Edit a note (owner only)","operationId":"update_note_api_notes__note_id__put","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Notes"],"summary":"Delete a note (owner only)","description":"Soft delete + attachment purge.\n\nRows go first, inside the transaction; the S3 objects follow best-effort,\nbecause an S3 hiccup must not undo a delete the user asked for. A leaked\nobject is a cost problem, a failed delete is a trust problem.","operationId":"delete_note_api_notes__note_id__delete","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/{note_id}/done":{"put":{"tags":["Notes"],"summary":"Mark a note done","operationId":"mark_done_api_notes__note_id__done_put","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Notes"],"summary":"Re-open a note","description":"Un-done. Reminders stay off — see notes_db.set_note_done.","operationId":"clear_done_api_notes__note_id__done_delete","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/{note_id}/read":{"put":{"tags":["Notes"],"summary":"Mark a shared note as read","description":"Clears this note from the caller's notes badge. Idempotent.","operationId":"mark_read_api_notes__note_id__read_put","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/{note_id}/shares":{"post":{"tags":["Notes"],"summary":"Share a note (owner only)","operationId":"share_note_api_notes__note_id__shares_post","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SharesPayload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/{note_id}/shares/{target_user_id}":{"delete":{"tags":["Notes"],"summary":"Un-share (owner only)","operationId":"unshare_note_api_notes__note_id__shares__target_user_id__delete","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"target_user_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Target User Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/{note_id}/reminder":{"put":{"tags":["Notes"],"summary":"Set my reminder on a note","description":"Owner or recipient — a reminder is per-user, not per-note.","operationId":"set_reminder_api_notes__note_id__reminder_put","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReminderPayload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Notes"],"summary":"Remove my reminder","operationId":"clear_reminder_api_notes__note_id__reminder_delete","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/{note_id}/attachments":{"post":{"tags":["Notes"],"summary":"Attach files (owner only)","operationId":"add_attachments_api_notes__note_id__attachments_post","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_add_attachments_api_notes__note_id__attachments_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/{note_id}/attachments/{attachment_id}/download":{"get":{"tags":["Notes"],"summary":"Presigned download URL","description":"Anyone who can see the note can download its files.","operationId":"download_attachment_api_notes__note_id__attachments__attachment_id__download_get","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"attachment_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Attachment Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notes/{note_id}/attachments/{attachment_id}":{"delete":{"tags":["Notes"],"summary":"Remove a file (owner only)","operationId":"remove_attachment_api_notes__note_id__attachments__attachment_id__delete","parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Note Id"}},{"name":"attachment_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Attachment Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/":{"get":{"tags":["Notifications"],"summary":"List Notifications","description":"List notifications for the authenticated user, newest first.","operationId":"list_notifications_api_notifications__get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"priority","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Priority"}},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Type"}},{"name":"unread_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Unread Only"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Notifications"],"summary":"Delete Notification","description":"Delete a single notification. Identified by sk (sort key) in body.","operationId":"delete_notification_api_notifications__delete","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/since":{"get":{"tags":["Notifications"],"summary":"List Notifications Since","description":"Return notifications with SK > cursor, oldest-first. Used by the client\nto catch up on missed pushes after a WS outage. Empty cursor returns [].","operationId":"list_notifications_since_api_notifications_since_get","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/unread-count":{"get":{"tags":["Notifications"],"summary":"Get Unread Count","description":"Get unread notification count for the authenticated user.","operationId":"get_unread_count_api_notifications_unread_count_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/read":{"patch":{"tags":["Notifications"],"summary":"Mark Notification Read","description":"Mark a single notification as read. Identified by sk (sort key) in body.","operationId":"mark_notification_read_api_notifications_read_patch","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/read-all":{"patch":{"tags":["Notifications"],"summary":"Mark All Read","description":"Mark all notifications as read for the authenticated user.","operationId":"mark_all_read_api_notifications_read_all_patch","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Notifications"],"summary":"Delete All Read","description":"Delete all read notifications for the authenticated user.","operationId":"delete_all_read_api_notifications_read_all_delete","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal-messages":{"get":{"tags":["Portal Messages"],"summary":"List Portal Messages","description":"List captured portal messages. Scope is resolved by ``_resolve_scope``:\na non-admin sees their own visible teams; an admin follows the board filters\n(funnel takes precedence, else selected users' teams, else the whole company).","operationId":"list_portal_messages_api_portal_messages_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"'unread' | 'read' | 'archived' | 'all'","default":"unread","title":"Status"},"description":"'unread' | 'read' | 'archived' | 'all'"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"user_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Leads board 'Utilizador' filter — resolved to those users' teams.","title":"User Ids"},"description":"Leads board 'Utilizador' filter — resolved to those users' teams."},{"name":"team_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Leads board 'Fluxo de Atribuição' filter (funnel/team ids).","title":"Team Ids"},"description":"Leads board 'Fluxo de Atribuição' filter (funnel/team ids)."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal-messages/unread-count":{"get":{"tags":["Portal Messages"],"summary":"Unread Count","description":"Number of unread portal messages. Scope follows the leads board filters,\nlike the list.","operationId":"unread_count_api_portal_messages_unread_count_get","parameters":[{"name":"user_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"User Ids"}},{"name":"team_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Team Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal-messages/{message_id}/read":{"patch":{"tags":["Portal Messages"],"summary":"Mark Read","description":"Mark a message read (team-shared) and log an 'opened' interaction.","operationId":"mark_read_api_portal_messages__message_id__read_patch","parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal-messages/{message_id}/link-click":{"post":{"tags":["Portal Messages"],"summary":"Link Click","description":"Log that the caller opened the portal deep link (history).","operationId":"link_click_api_portal_messages__message_id__link_click_post","parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal-messages/{message_id}/views":{"get":{"tags":["Portal Messages"],"summary":"List Views","description":"Interaction history (who opened / clicked, when) for a message.","operationId":"list_views_api_portal_messages__message_id__views_get","parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal-messages/{message_id}/convert-to-lead":{"post":{"tags":["Portal Messages"],"summary":"Convert To Lead","description":"Create a lead from a captured portal message (buyer data entered by the\nuser — the portal email has none). Reuses the normal lead pipeline; the lead\ninherits the message's team and keeps the chat URL. Idempotent: a message\nalready converted returns its existing lead instead of creating another.","operationId":"convert_to_lead_api_portal_messages__message_id__convert_to_lead_post","parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertLeadBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/lead-recontact-alerts":{"get":{"tags":["Lead Recontact Alerts"],"summary":"List Alerts","description":"List recontact alerts (newest first).\n\nScope: a company **admin** may follow the leads board's filters\n(``user_ids``/``team_ids``) and sees the whole company by default — so the\nbanner mirrors what the board shows for anyone doing oversight. A **non-admin**\nalways stays scoped to their own visible teams and cannot widen via the\nclient-supplied filters.","operationId":"list_alerts_api_lead_recontact_alerts_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"'unread' | 'read' | 'archived' | 'all'","default":"all","title":"Status"},"description":"'unread' | 'read' | 'archived' | 'all'"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"user_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Leads board 'Utilizador' filter — scope alerts to these lead owners.","title":"User Ids"},"description":"Leads board 'Utilizador' filter — scope alerts to these lead owners."},{"name":"team_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Leads board 'Fluxo de Atribuição' filter — scope alerts to these funnels.","title":"Team Ids"},"description":"Leads board 'Fluxo de Atribuição' filter — scope alerts to these funnels."},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/lead-recontact-alerts/unread-count":{"get":{"tags":["Lead Recontact Alerts"],"summary":"Unread Count","description":"Number of OPEN (unread) alerts of any kind — the banner number. Revived\nleads count too (product decision 2026-07-10: a revive shows in the banner\n+ dialog *and* as the card badge). Scope follows the same admin/non-admin\nrule as the list.","operationId":"unread_count_api_lead_recontact_alerts_unread_count_get","parameters":[{"name":"user_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"User Ids"}},{"name":"team_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Team Ids"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/lead-recontact-alerts/{alert_id}/read":{"patch":{"tags":["Lead Recontact Alerts"],"summary":"Mark Read","description":"Mark an alert read (team-shared). Dismisses the banner row; does NOT\nundo a revive (the lead stays in 'Por Contactar').","operationId":"mark_read_api_lead_recontact_alerts__alert_id__read_patch","parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"integer","title":"Alert Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/nudges":{"get":{"tags":["Nudges"],"summary":"List Nudges","description":"Gestor IA feed — recommendations computed ON DEMAND for the caller's company\n(cached ~1h; ``refresh=1`` recomputes), overlaid with the interaction ledger and\nthe 'Foco da semana'. Superset of the legacy shape (adds computed_at,\nhealth_score, health_factors, focus).","operationId":"list_nudges_api_nudges_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"'all' | 'new' | 'seen' | 'acted' | 'dismissed'","default":"all","title":"Status"},"description":"'all' | 'new' | 'seen' | 'acted' | 'dismissed'"},{"name":"refresh","in":"query","required":false,"schema":{"type":"integer","maximum":1,"minimum":0,"description":"1 = bypass cache and recompute (the 'Atualizar' button)","default":0,"title":"Refresh"},"description":"1 = bypass cache and recompute (the 'Atualizar' button)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/nudges/export":{"get":{"tags":["Nudges"],"summary":"Export Nudges","description":"Excel do feed Gestor IA: folha 'Resumo' (saúde, fatores, foco) e folha\n'Sugestões' (uma linha por sugestão). Lê o MESMO feed em cache que o ecrã\nmostra — sem ``refresh``, para o ficheiro nunca contradizer o que o\nutilizador acabou de ver (e não gastar o orçamento de refreshes/minuto).","operationId":"export_nudges_api_nudges_export_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/nudges/unread-count":{"get":{"tags":["Nudges"],"summary":"Unread Count","description":"Number of 'new' nudges visible to the caller — the bell badge number.","operationId":"unread_count_api_nudges_unread_count_get","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/nudges/interaction":{"patch":{"tags":["Nudges"],"summary":"Mark Interaction","description":"Record a user interaction against a live card by its ``dedupe_key`` (the new\nFE path — cards are computed on demand and may not have a numeric id yet).\nUpserts the ledger row if needed (no bell) and transitions its state.","operationId":"mark_interaction_api_nudges_interaction_patch","parameters":[{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InteractionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/nudges/{nudge_id}/seen":{"patch":{"tags":["Nudges"],"summary":"Mark Seen","description":"Mark a nudge seen (new -> seen). No-op if already past 'new'.","operationId":"mark_seen_api_nudges__nudge_id__seen_patch","parameters":[{"name":"nudge_id","in":"path","required":true,"schema":{"type":"integer","title":"Nudge Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/nudges/{nudge_id}/acted":{"patch":{"tags":["Nudges"],"summary":"Mark Acted","description":"Mark a nudge acted-upon (the user did the suggested thing).","operationId":"mark_acted_api_nudges__nudge_id__acted_patch","parameters":[{"name":"nudge_id","in":"path","required":true,"schema":{"type":"integer","title":"Nudge Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/nudges/{nudge_id}/dismissed":{"patch":{"tags":["Nudges"],"summary":"Mark Dismissed","description":"Dismiss a nudge (the user chose to ignore it).","operationId":"mark_dismissed_api_nudges__nudge_id__dismissed_patch","parameters":[{"name":"nudge_id","in":"path","required":true,"schema":{"type":"integer","title":"Nudge Id"}},{"name":"x-api-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/callback":{"get":{"tags":["Authentication"],"summary":"Auth Callback","description":"Cognito OAuth2 callback endpoint.\nExchanges 'code' for tokens, stores them as secure HttpOnly cookies,\nand redirects the user to the original app URL.","operationId":"auth_callback_api_auth_callback_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}},{"name":"state","in":"query","required":true,"schema":{"type":"string","title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/refresh":{"post":{"tags":["Authentication"],"summary":"Refresh Token","operationId":"refresh_token_api_auth_refresh_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/logout":{"post":{"tags":["Authentication"],"summary":"Logout","operationId":"logout_api_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/health":{"get":{"tags":["System"],"summary":"Health Check","operationId":"health_check_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AdDescriptionRequest":{"properties":{"listing_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Listing Id"},"marca":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marca"},"modelo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Modelo"},"versao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Versao"},"ano":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ano"},"kms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Kms"},"combustivel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Combustivel"},"potencia":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Potencia"},"cor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cor"},"mes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mes"},"portas":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Portas"},"transmissao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transmissao"},"lugares":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lugares"},"cilindrada":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cilindrada"},"pv_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pv Id"},"max_words":{"type":"integer","title":"Max Words","default":50},"tone":{"type":"string","title":"Tone","default":"profissional mas apelativo"},"language":{"type":"string","title":"Language","default":"Portugues de Portugal"}},"type":"object","title":"AdDescriptionRequest","description":"Request to generate vehicle ad description."},"AdDescriptionResponse":{"properties":{"description":{"type":"string","title":"Description"},"model_used":{"type":"string","title":"Model Used","default":"deepseek-chat"}},"type":"object","required":["description"],"title":"AdDescriptionResponse","description":"Response with generated ad description."},"AddressCreate":{"properties":{"morada":{"type":"string","maxLength":255,"title":"Morada"},"codigo_postal":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Codigo Postal"},"localidade":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Localidade"},"cidade":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Cidade"},"pais":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Pais"},"principal":{"type":"boolean","title":"Principal","description":"Is this the primary address","default":false}},"type":"object","required":["morada"],"title":"AddressCreate","description":"Address creation request."},"AddressResponse":{"properties":{"id":{"type":"integer","title":"Id"},"morada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Morada"},"codigo_postal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codigo Postal"},"localidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localidade"},"cidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cidade"},"pais":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pais"},"principal":{"type":"boolean","title":"Principal","default":false}},"type":"object","required":["id"],"title":"AddressResponse","description":"Address response."},"AddressUpdate":{"properties":{"morada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Morada"},"codigo_postal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codigo Postal"},"localidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localidade"},"cidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cidade"},"pais":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pais"},"principal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Principal"}},"type":"object","title":"AddressUpdate","description":"Address update request (all fields optional)."},"AdminCreateRegistrationRequest":{"properties":{"company_name":{"type":"string","title":"Company Name"},"nipc":{"type":"string","title":"Nipc"},"personal_name":{"type":"string","title":"Personal Name"},"personal_email":{"type":"string","title":"Personal Email"},"personal_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Personal Phone","default":""},"promo_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Promo Code"},"plan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Plan Id"},"company_billing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Company Billing","default":false}},"type":"object","required":["company_name","nipc","personal_name","personal_email"],"title":"AdminCreateRegistrationRequest"},"AgreementCreate":{"properties":{"idpointofsale":{"type":"integer","title":"Idpointofsale"},"percentagem":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Percentagem"},"inicio":{"type":"string","format":"date","title":"Inicio"},"fim":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Fim"}},"type":"object","required":["idpointofsale","percentagem","inicio"],"title":"AgreementCreate","description":"Body for POST /api/socios/{id}/agreements — submits AGREEMENT_CREATE."},"AgreementResponse":{"properties":{"id":{"type":"integer","title":"Id"},"partner_id":{"type":"integer","title":"Partner Id"},"idpointofsale":{"type":"integer","title":"Idpointofsale"},"percentagem":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Percentagem"},"inicio":{"type":"string","format":"date","title":"Inicio"},"fim":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Fim"},"active":{"type":"boolean","title":"Active"},"superseded_by":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Superseded By"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","partner_id","idpointofsale","percentagem","inicio","active"],"title":"AgreementResponse"},"AgreementUpdate":{"properties":{"percentagem":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Percentagem"},"fim":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Fim","description":"Set to end the agreement on a future date without a successor"}},"type":"object","title":"AgreementUpdate","description":"Body for PUT /api/socios/{id}/agreements/{agreement_id}.\n\nThe apply step is close-and-replace: the in-flight row gets fim/active=0/\nsuperseded_by, and a new row with the new percentagem is inserted."},"ApprovalRow":{"properties":{"partner_id":{"type":"integer","title":"Partner Id"},"partner_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Partner Name"},"vote":{"type":"string","enum":["PENDING","APPROVED","REJECTED"],"title":"Vote"},"voted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Voted At"},"voted_by":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Voted By"}},"type":"object","required":["partner_id","vote"],"title":"ApprovalRow","description":"One approver's vote on a change request."},"Article":{"properties":{"id":{"type":"integer","title":"Id"},"id_website":{"type":"integer","title":"Id Website"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"pdf_desktop":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pdf Desktop"},"pdf_mobile":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pdf Mobile"},"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"},"reactjson":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reactjson"}},"type":"object","required":["id","id_website"],"title":"Article"},"AssetListResponse":{"properties":{"folders":{"items":{"type":"string"},"type":"array","title":"Folders"},"files":{"items":{"type":"string"},"type":"array","title":"Files"},"truncated":{"type":"boolean","title":"Truncated","default":false}},"type":"object","required":["folders","files"],"title":"AssetListResponse","description":"Response shape for /assets/list.\n\n⚠️ This used to be `Dict[str, List[str]]`, which made the response model\nitself the reason no non-list field could ever be added — returning\n`truncated: bool` under that model fails response validation and 500s the\nendpoint for every consumer. Add new fields HERE, not to a bare dict."},"AutoFromNifRequest":{"properties":{"nif":{"type":"string","maxLength":50,"minLength":1,"title":"Nif"}},"type":"object","required":["nif"],"title":"AutoFromNifRequest","description":"Auto-create-from-NIF request body."},"AutoFromNifResponse":{"properties":{"created":{"type":"boolean","title":"Created"},"exists":{"type":"boolean","title":"Exists","default":false},"client_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Client Id"},"nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["created"],"title":"AutoFromNifResponse","description":"Auto-create-from-NIF structured outcome (always HTTP 200)."},"BankRow":{"properties":{"id":{"type":"integer","title":"Id"},"metodo_pagamento_id":{"type":"integer","title":"Metodo Pagamento Id"},"ponto_venda_id":{"type":"integer","title":"Ponto Venda Id"},"date_value":{"type":"string","format":"date","title":"Date Value"},"description":{"type":"string","title":"Description"},"amount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,16}|(?=[\\d.]{1,19}0*$)\\d{0,16}\\.\\d{0,2}0*$)","title":"Amount"},"reconciled":{"type":"string","title":"Reconciled"},"reconciled_amount":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,16}|(?=[\\d.]{1,19}0*$)\\d{0,16}\\.\\d{0,2}0*$)"},{"type":"null"}],"title":"Reconciled Amount"},"invoices":{"items":{"$ref":"#/components/schemas/ReconciliationInvoice"},"type":"array","title":"Invoices","default":[]},"identical_elsewhere":{"items":{"$ref":"#/components/schemas/IdenticalMovement"},"type":"array","title":"Identical Elsewhere","default":[]},"ignored":{"type":"boolean","title":"Ignored","default":false},"ignored_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ignored Reason"},"ignored_by":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ignored By"},"ignored_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ignored At"},"statement_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Statement Id"},"seq":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seq"},"sign_verified":{"type":"boolean","title":"Sign Verified","default":false}},"type":"object","required":["id","metodo_pagamento_id","ponto_venda_id","date_value","description","amount","reconciled","reconciled_amount"],"title":"BankRow"},"Banner":{"properties":{"id":{"type":"integer","title":"Id"},"idwebsite":{"type":"integer","title":"Idwebsite"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"urlmobile":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Urlmobile"},"redirecturl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirecturl"},"idservice":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idservice"}},"type":"object","required":["id","idwebsite"],"title":"Banner"},"BatchEventItem":{"properties":{"visitor_id":{"type":"string","title":"Visitor Id"},"event_type":{"type":"string","title":"Event Type"},"page_url":{"type":"string","title":"Page Url"},"page_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page Title"},"event_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Name"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["visitor_id","event_type","page_url"],"title":"BatchEventItem"},"BatchEventsRequest":{"properties":{"events":{"items":{"$ref":"#/components/schemas/BatchEventItem"},"type":"array","title":"Events","description":"List of events to track"},"utm":{"anyOf":[{"$ref":"#/components/schemas/UTMParams"},{"type":"null"}],"description":"UTM parameters (shared)"}},"type":"object","required":["events"],"title":"BatchEventsRequest"},"BatchUpdateResponse":{"properties":{"updated_count":{"type":"integer","title":"Updated Count"},"total_requested":{"type":"integer","title":"Total Requested"},"status":{"type":"string","title":"Status"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"updated_ids":{"items":{"type":"integer"},"type":"array","title":"Updated Ids","default":[]}},"type":"object","required":["updated_count","total_requested","status"],"title":"BatchUpdateResponse"},"Body_add_attachments_api_notes__note_id__attachments_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Máx. 5 por nota, 10MB cada","default":[]}},"type":"object","title":"Body_add_attachments_api_notes__note_id__attachments_post"},"Body_add_message_api_tickets__ticket_id__messages_post":{"properties":{"message":{"type":"string","title":"Message","description":"Reply message"},"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Attachments","default":[]}},"type":"object","required":["message"],"title":"Body_add_message_api_tickets__ticket_id__messages_post"},"Body_admin_add_message_api_admin_tickets__ticket_id__messages_post":{"properties":{"message":{"type":"string","title":"Message","description":"Admin reply message"},"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Attachments","default":[]}},"type":"object","required":["message"],"title":"Body_admin_add_message_api_admin_tickets__ticket_id__messages_post"},"Body_admin_add_note_api_admin_tickets__ticket_id__notes_post":{"properties":{"note":{"type":"string","title":"Note","description":"Internal note (admins only)"},"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Attachments","default":[]}},"type":"object","required":["note"],"title":"Body_admin_add_note_api_admin_tickets__ticket_id__notes_post"},"Body_admin_create_ticket_api_admin_tickets_post":{"properties":{"subject":{"type":"string","title":"Subject","description":"Ticket subject"},"description":{"type":"string","title":"Description","description":"Ticket description"},"priority":{"type":"string","title":"Priority","description":"Priority: low, medium, high, urgent","default":"medium"},"internal_priority":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Internal Priority","description":"Admin-only priority (never shown to users)"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category","description":"Category (admins may also use: integracoes)"},"assigned_to":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Assigned To","description":"Assign to a system_admin"},"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Attachments (max 5 files, 10MB each)","default":[]}},"type":"object","required":["subject","description"],"title":"Body_admin_create_ticket_api_admin_tickets_post"},"Body_api_create_leave_api_leaves_post":{"properties":{"leave_type":{"type":"string","title":"Leave Type"},"start_date":{"type":"string","title":"Start Date"},"end_date":{"type":"string","title":"End Date"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"document":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Document"}},"type":"object","required":["leave_type","start_date","end_date"],"title":"Body_api_create_leave_api_leaves_post"},"Body_api_import_bank_rows_api_bank_rows_import_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"metodo_pagamento_id":{"type":"integer","title":"Metodo Pagamento Id"},"ponto_venda_id":{"type":"integer","title":"Ponto Venda Id"},"confirm_import_all":{"type":"boolean","title":"Confirm Import All","description":"Write every movement in the file, including those in periods already imported. Support escape hatch — normally the importer skips them.","default":false}},"type":"object","required":["file","metodo_pagamento_id","ponto_venda_id"],"title":"Body_api_import_bank_rows_api_bank_rows_import_post"},"Body_attach_comprovativo_batch_api_financeiro_movements_comprovativo_batch_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"movement_ids":{"type":"string","title":"Movement Ids","description":"IDs dos movimentos, separados por vírgulas"},"tipodoc":{"type":"integer","title":"Tipodoc","description":"Tipo de documento (59 = Comprovativo Pagamento)","default":59}},"type":"object","required":["file","movement_ids"],"title":"Body_attach_comprovativo_batch_api_financeiro_movements_comprovativo_batch_post"},"Body_conclude_transporte_api_transportes__transport_id__concluir_post":{"properties":{"foto_cmr":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Foto Cmr"},"foto_parque":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Foto Parque"}},"type":"object","title":"Body_conclude_transporte_api_transportes__transport_id__concluir_post"},"Body_create_document_api_documents_test__post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"tipodoc":{"type":"integer","title":"Tipodoc","description":"Document type ID"},"id_modulo":{"type":"integer","title":"Id Modulo","description":"Module ID"},"id_modulo_id":{"type":"integer","title":"Id Modulo Id","description":"Record ID within module"},"data_expira":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Expira","description":"Expiration date YYYY-MM-DD"},"id_doc_assinado":{"type":"integer","title":"Id Doc Assinado","description":"ID of signed document version","default":0}},"type":"object","required":["file","tipodoc","id_modulo","id_modulo_id"],"title":"Body_create_document_api_documents_test__post"},"Body_create_fatura_api_invoices_post":{"properties":{"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"},"A":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"A","description":"Emitter NIF (Portuguese 9-digit or foreign alphanumeric)"},"B":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"B","description":"Acquirer NIF (Portuguese 9-digit or foreign alphanumeric)"},"C":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"C"},"D":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"D"},"E":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"E"},"F":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"F","description":"Document date YYYY-MM-DD"},"G":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"G","description":"Invoice number"},"H":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"H","description":"ATCUD"},"I1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I1"},"I2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I2"},"I3":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I3"},"I4":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I4"},"I5":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I5"},"I6":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I6"},"I7":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I7"},"I8":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I8"},"J1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J1"},"J2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J2"},"J3":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J3"},"J4":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J4"},"J5":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J5"},"J6":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J6"},"J7":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J7"},"J8":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J8"},"K1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K1"},"K2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K2"},"K3":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K3"},"K4":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K4"},"K5":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K5"},"K6":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K6"},"K7":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K7"},"K8":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K8"},"L":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"L"},"M":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"M"},"N":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"N","description":"Tax total"},"O":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"O","description":"Grand total"},"P":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"P"},"Q":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"},"R":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"R"},"S":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"S"},"Descricao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Descricao"},"tipodocs":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tipodocs","description":"Document type ID"},"emitente_nif":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Emitente Nif","description":"Emitter NIF (maps to A)"},"adquirente_nif":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Adquirente Nif","description":"Acquirer NIF (maps to B)"},"data_documento":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Documento","description":"Document date (maps to F)"},"numero":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Numero","description":"Invoice number (maps to G)"},"atcud":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Atcud","description":"ATCUD (maps to H)"},"base_tributavel":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Base Tributavel","description":"Tax base (maps to I7)"},"total_iva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Iva","description":"Total VAT (maps to N)"},"total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total","description":"Grand total (maps to O)"},"retencao_na_fonte":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Retencao Na Fonte","description":"Retenção na Fonte / withholding (maps to P)"},"descricao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Descricao","description":"Description (maps to Descricao)"},"tipo_documento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tipo Documento","description":"Document type ID (maps to tipodocs)"},"pre_enhanced":{"type":"boolean","title":"Pre Enhanced","description":"Skip server-side digitalization (file already cleaned by /invoices/digitalize-image)","default":false}},"type":"object","title":"Body_create_fatura_api_invoices_post"},"Body_create_fatura_legacy_public_faturas_post":{"properties":{"empresa":{"type":"string","title":"Empresa","description":"Company ID"},"user_id":{"type":"string","title":"User Id","description":"User ID"},"idpv":{"type":"string","title":"Idpv","description":"Point of Sale ID"},"idmodulo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idmodulo","description":"Module ID (8=Faturas)"},"tipo_doc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tipo Doc","description":"Document type (maps to tipodocs)"},"dataentrada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dataentrada","description":"Entry date DD/MM/YYYY"},"Scanner":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scanner","description":"Scanner field (ignored)"},"A":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"A","description":"Emitter NIF"},"B":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"B","description":"Acquirer NIF"},"C":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"C"},"D":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"D"},"E":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"E"},"F":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"F","description":"Document date YYYY-MM-DD"},"G":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"G","description":"Invoice number"},"H":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"H","description":"ATCUD"},"I1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I1"},"I2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I2"},"I3":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I3"},"I4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I4"},"I5":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I5"},"I6":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I6"},"I7":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I7","description":"Tax base"},"I8":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I8","description":"Tax amount"},"J1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J1"},"J2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J2"},"J3":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J3"},"J4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J4"},"J5":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J5"},"J6":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J6"},"J7":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J7"},"J8":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J8"},"K1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K1"},"K2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K2"},"K3":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K3"},"K4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K4"},"K5":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K5"},"K6":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K6"},"K7":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K7"},"K8":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K8"},"L":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"L"},"M":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"M"},"N":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"N","description":"Tax total"},"O":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"O","description":"Grand total"},"P":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"P"},"Q":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"},"R":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"R"},"S":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"S"},"Descricao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Descricao"},"files":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Files","description":"Invoice file (PDF/image)"}},"type":"object","required":["empresa","user_id","idpv"],"title":"Body_create_fatura_legacy_public_faturas_post"},"Body_create_lead_backoffice_api_leads_post":{"properties":{"phone":{"type":"string","title":"Phone"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Origin"},"assigned_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Assigned User Id"},"team_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Team Id"},"vehicle_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vehicle Id"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"fromurl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fromurl"},"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Source"},"utm_medium":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Medium"},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Campaign"}},"type":"object","required":["phone"],"title":"Body_create_lead_backoffice_api_leads_post"},"Body_create_lead_public_leads_post":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"type":"string","title":"Phone"},"visitor_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Visitor Id"},"stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Origin"},"assigned_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Assigned User Id"},"team_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Team Id"},"idpos":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idpos"},"fromurl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fromurl"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"object_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Object Id"},"files":{"anyOf":[{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array"},{"type":"null"}],"title":"Files"},"file_doc_type_ids_in_order":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Doc Type Ids In Order"}},"type":"object","required":["phone"],"title":"Body_create_lead_public_leads_post"},"Body_create_ticket_api_tickets_post":{"properties":{"subject":{"type":"string","title":"Subject","description":"Ticket subject"},"description":{"type":"string","title":"Description","description":"Ticket description"},"priority":{"type":"string","title":"Priority","description":"Priority: low, medium, high, urgent","default":"medium"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category","description":"Category: falha_tecnica, duvida, sugestao_melhoria"},"assigned_to":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Assigned To","description":"Assign to a system_admin (system_admin only)"},"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Attachments (max 5 files, 10MB each)","default":[]}},"type":"object","required":["subject","description"],"title":"Body_create_ticket_api_tickets_post"},"Body_digitalize_image_api_invoices_digitalize_image_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_digitalize_image_api_invoices_digitalize_image_post"},"Body_import_document_api_declaration_templates_import_document_post":{"properties":{"files":{"anyOf":[{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array"},{"type":"null"}],"title":"Files"},"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"},"id_modulo":{"type":"integer","title":"Id Modulo"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"trigger_action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trigger Action"},"tipo_doc":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tipo Doc"},"instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions"}},"type":"object","required":["id_modulo"],"title":"Body_import_document_api_declaration_templates_import_document_post"},"Body_import_workbook_api_vehicle_import_excel_import_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"pv_id":{"type":"integer","title":"Pv Id"},"update":{"type":"boolean","title":"Update","default":true},"strict":{"type":"boolean","title":"Strict","default":false}},"type":"object","required":["file","pv_id"],"title":"Body_import_workbook_api_vehicle_import_excel_import_post"},"Body_ocr_citizen_card_api_clients_ocr_document_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Cartão de Cidadão (frente e, opcionalmente, verso)"}},"type":"object","required":["files"],"title":"Body_ocr_citizen_card_api_clients_ocr_document_post"},"Body_ocr_driving_license_api_clients_ocr_driving_license_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Carta de Condução (frente e, opcionalmente, verso ou PDF)"}},"type":"object","required":["files"],"title":"Body_ocr_driving_license_api_clients_ocr_driving_license_post"},"Body_ocr_vehicle_document_api_vehicles_ocr_document_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Documento do veículo (frente e, opcionalmente, verso)"}},"type":"object","required":["files"],"title":"Body_ocr_vehicle_document_api_vehicles_ocr_document_post"},"Body_process_qr_api_invoices_process_qr_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_process_qr_api_invoices_process_qr_post"},"Body_register_company_public_register_post":{"properties":{"company_name":{"type":"string","title":"Company Name"},"nipc":{"type":"string","title":"Nipc"},"personal_name":{"type":"string","title":"Personal Name"},"personal_email":{"type":"string","title":"Personal Email"},"personal_phone":{"type":"string","title":"Personal Phone"},"cae_document":{"type":"string","contentMediaType":"application/octet-stream","title":"Cae Document"},"promo_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Promo Code"}},"type":"object","required":["company_name","nipc","personal_name","personal_email","personal_phone","cae_document"],"title":"Body_register_company_public_register_post"},"Body_save_vehicle_photos_api_vehicles__vehicle_id__photos_post":{"properties":{"files":{"anyOf":[{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array"},{"type":"null"}],"title":"Files","description":"New image files to upload"},"photos":{"type":"string","title":"Photos","description":"JSON array of photos [{url, sort_order}] - REQUIRED"},"new_photos_sort_order":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"New Photos Sort Order","description":"JSON array of target ordem values for new files, parallel to files[]. When present, length must equal len(files). When omitted, new files are appended at the end (max(existing.sort_order) + i + 1)."}},"type":"object","required":["photos"],"title":"Body_save_vehicle_photos_api_vehicles__vehicle_id__photos_post"},"Body_send_email_with_attachments_api_email_send_post":{"properties":{"to":{"type":"string","format":"email","title":"To","description":"Recipient email address"},"subject":{"type":"string","title":"Subject","description":"Email subject"},"body":{"type":"string","title":"Body","description":"Plain text body"},"html_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Html Body","description":"Optional HTML body"},"html_signature":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Html Signature","description":"Optional HTML signature","default":""},"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Attachments","default":[]}},"type":"object","required":["to","subject","body"],"title":"Body_send_email_with_attachments_api_email_send_post"},"Body_send_inbox_email_api_system_admin_inbox_send_post":{"properties":{"mailbox":{"type":"string","title":"Mailbox","default":"info"},"to":{"type":"string","title":"To","description":"Comma-separated recipient list"},"subject":{"type":"string","title":"Subject","default":""},"html_body":{"type":"string","title":"Html Body","default":""},"cc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cc"},"bcc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bcc"},"in_reply_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"In Reply To"},"references":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"References"},"apply_signature":{"type":"boolean","title":"Apply Signature","description":"Append user signature if not already present","default":true},"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","default":[]}},"type":"object","required":["to"],"title":"Body_send_inbox_email_api_system_admin_inbox_send_post"},"Body_set_page_body_api_configs_body__domain__post":{"properties":{"content":{"type":"string","title":"Content"}},"type":"object","required":["content"],"title":"Body_set_page_body_api_configs_body__domain__post"},"Body_set_page_header_api_configs_header__domain__post":{"properties":{"content":{"type":"string","title":"Content"}},"type":"object","required":["content"],"title":"Body_set_page_header_api_configs_header__domain__post"},"Body_upload_assets_api_assets_upload_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_upload_assets_api_assets_upload_post"},"Body_upload_draft_attachment_api_system_admin_inbox_drafts__draft_id__attachments_post":{"properties":{"mailbox":{"type":"string","title":"Mailbox","default":"info"},"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_draft_attachment_api_system_admin_inbox_drafts__draft_id__attachments_post"},"Body_upload_file_public_onboarding_questionnaire__token__uploads__kind__post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_file_public_onboarding_questionnaire__token__uploads__kind__post"},"Body_upload_multidrive_api_multidrive_upload_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_upload_multidrive_api_multidrive_upload_post"},"Body_upload_photo_api_checkups_upload_photo_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_photo_api_checkups_upload_photo_post"},"Body_upload_user_photo_api_users__user_id__photo_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_user_photo_api_users__user_id__photo_post"},"Body_upload_vehicle_photos_api_vehicles__vehicle_id__photos_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Image files to upload"},"replace_existing":{"type":"boolean","title":"Replace Existing","description":"Delete existing photos before upload","default":false}},"type":"object","required":["files"],"title":"Body_upload_vehicle_photos_api_vehicles__vehicle_id__photos_post"},"Body_validate_workbook_api_vehicle_import_excel_validate_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"pv_id":{"type":"integer","title":"Pv Id"},"strict":{"type":"boolean","title":"Strict","default":false}},"type":"object","required":["file","pv_id"],"title":"Body_validate_workbook_api_vehicle_import_excel_validate_post"},"BrandActionResult":{"properties":{"brand_id":{"type":"integer","title":"Brand Id"},"action":{"type":"string","title":"Action"},"reason":{"type":"string","title":"Reason"},"job_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Job Id"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"platforms_to_publish":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Platforms To Publish"},"platforms_to_unpublish":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Platforms To Unpublish"}},"type":"object","required":["brand_id","action","reason"],"title":"BrandActionResult","description":"Result of Integrazu action for a single brand."},"BrandComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Marca":{"type":"string","title":"Marca"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"}},"type":"object","required":["ID","Marca"],"title":"BrandComboItem","description":"Brand dropdown item."},"BrandExportConfig":{"properties":{"brand_id":{"type":"integer","title":"Brand Id","description":"Z_Brands.id for Integrazu token lookup"},"platforms":{"items":{"type":"string"},"type":"array","title":"Platforms","description":"List of platforms to publish to (e.g., 'carmine', 'standvirtual')"},"website_ids":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Website Ids","description":"List of website IDs this brand exports to"},"renew":{"type":"boolean","title":"Renew","description":"If True, auto-renew on platforms. Stored in Z_PortalExports.renew","default":false},"export_olx_through_standvirtual":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Export Olx Through Standvirtual","description":"If true, promote OLX via StandVirtual after publishing"}},"type":"object","required":["brand_id","platforms"],"title":"BrandExportConfig","description":"Configuration for publishing a listing to a specific brand's Integrazu account."},"BrandPublishConfig":{"properties":{"brand_id":{"type":"integer","title":"Brand Id","description":"Z_Brands.id for Integrazu token lookup"},"platforms":{"items":{"type":"string"},"type":"array","title":"Platforms","description":"List of platforms to publish to for this brand"},"website_ids":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Website Ids","description":"List of Websites.id to export this listing to (Z_WebsiteExports). Optional."},"renew":{"type":"boolean","title":"Renew","description":"If True, the advert will auto-renew on platforms. Stored in Z_PortalExports.renew","default":false}},"type":"object","required":["brand_id","platforms"],"title":"BrandPublishConfig","description":"Configuration for publishing to a specific brand."},"CashResponse":{"properties":{"total_paid":{"type":"number","title":"Total Paid"},"total_unpaid":{"type":"number","title":"Total Unpaid"},"total_balance":{"type":"number","title":"Total Balance"},"cash_by_method":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Cash By Method"},"currency":{"type":"string","title":"Currency","default":"EUR"},"last_updated":{"type":"string","title":"Last Updated"}},"type":"object","required":["total_paid","total_unpaid","total_balance","cash_by_method","last_updated"],"title":"CashResponse"},"CategoryComboItem":{"properties":{"Id":{"type":"integer","title":"Id"},"Tipo":{"type":"string","title":"Tipo"}},"type":"object","required":["Id","Tipo"],"title":"CategoryComboItem","description":"Vehicle category/type (tipo) dropdown item."},"ChangeRequestResponse":{"properties":{"id":{"type":"integer","title":"Id"},"idcompany":{"type":"integer","title":"Idcompany"},"change_type":{"type":"string","enum":["PARTNER_CREATE","PARTNER_UPDATE","PARTNER_DELETE","AGREEMENT_CREATE","AGREEMENT_UPDATE","AGREEMENT_DELETE","PV_ROSTER_REPLACE"],"title":"Change Type"},"target_partner_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Target Partner Id"},"target_agreement_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Target Agreement Id"},"target_pv_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Target Pv Id"},"payload":{"additionalProperties":true,"type":"object","title":"Payload"},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED","EXPIRED","APPLIED"],"title":"Status"},"requested_by":{"type":"integer","title":"Requested By"},"requested_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requested By Name"},"requested_at":{"type":"string","format":"date-time","title":"Requested At"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resolved At"},"applied_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Applied At"},"apply_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Apply Error"},"pending_approver_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pending Approver Names"},"pending_approver_count":{"type":"integer","title":"Pending Approver Count","default":0},"total_approver_count":{"type":"integer","title":"Total Approver Count","default":0},"approvals":{"items":{"$ref":"#/components/schemas/ApprovalRow"},"type":"array","title":"Approvals","default":[]}},"type":"object","required":["id","idcompany","change_type","payload","status","requested_by","requested_at"],"title":"ChangeRequestResponse","description":"GET /api/socios/change-requests/* response shape."},"ChangeRequestSubmitResponse":{"properties":{"change_request_id":{"type":"integer","title":"Change Request Id"},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED","EXPIRED","APPLIED"],"title":"Status"},"approvers_pending":{"items":{"$ref":"#/components/schemas/PendingApprover"},"type":"array","title":"Approvers Pending","default":[]},"applied_entity_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Applied Entity Id"}},"type":"object","required":["change_request_id","status"],"title":"ChangeRequestSubmitResponse","description":"Return shape for any mutation endpoint.\n\nIf the request applied immediately (bootstrap / requester is sole sócio),\n`status` is APPLIED and the new entity's id (if any) is in `applied_entity_id`.\nOtherwise status is PENDING and the caller waits on votes."},"CitizenCardOcrResult":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"billed":{"type":"boolean","title":"Billed","default":false},"doc_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doc Type"},"confianca":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confianca"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","default":[]},"nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"nif":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nif"},"numero_documento":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Numero Documento"},"validade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validade"},"entidade_emissora":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entidade Emissora"}},"type":"object","title":"CitizenCardOcrResult","description":"Result of POST /api/clients/ocr-document (mirrors VehicleOcrResult): flat\nfields + success/error_message — an unreadable document is success=False,\nnever a 500. Data-minimized: only fields with a Cliente column are returned\n(no DOB/sex/filiação/NISS). This endpoint processes the images in memory and\nnever persists them; if the client is created, the frontend attaches them as\nDocumentos do cliente (módulo 12, tipo CC) via POST /documents-test/ — same\nretention as a manual upload. No client created, nothing stored."},"ClientBlockResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"},"contacto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contacto"},"CC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cc","description":"ID card number"},"ValidadeCC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validadecc","description":"ID card validity"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"EntidadeEmissoraCC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entidadeemissoracc","description":"ID card issuer"},"CartaConducao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cartaconducao","description":"Driver's license"},"DataCartaConducao":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datacartaconducao","description":"Driver's license date"},"NIF":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nif","description":"Tax ID"},"addresses":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Addresses","description":"Client addresses"}},"type":"object","required":["ID","Nome","contacto","email"],"title":"ClientBlockResponse","description":"Client data for contract block."},"ClientComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"},"NIF":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nif"}},"type":"object","required":["ID","Nome"],"title":"ClientComboItem","description":"Client dropdown item."},"ClientCreate":{"properties":{"nome":{"type":"string","maxLength":255,"minLength":1,"title":"Nome"},"email":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Email"},"contacto":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Contacto"},"nif":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Nif","description":"Tax ID (unique per company)"},"cc":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Cc","description":"ID card number"},"validade_cc":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Validade Cc","description":"ID card validity"},"entidade_emissora_cc":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Entidade Emissora Cc"},"particular":{"type":"boolean","title":"Particular","description":"True=Individual, False=Company","default":true},"recorrente":{"type":"boolean","title":"Recorrente","description":"Is recurring client","default":false},"carta_conducao":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Carta Conducao"},"data_carta_conducao":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Data Carta Conducao"},"iban":{"anyOf":[{"type":"string","maxLength":34},{"type":"null"}],"title":"Iban"},"iban_alimentar":{"anyOf":[{"type":"string","maxLength":34},{"type":"null"}],"title":"Iban Alimentar"},"pais":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Pais"},"morada":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Morada"},"codigo_postal":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Codigo Postal"},"localidade":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Localidade"},"cidade":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Cidade"},"id_pontodevenda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Pontodevenda"},"id_estado_civil":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Estado Civil"},"id_tipo_casa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Tipo Casa"},"id_contrato_trabalho":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Contrato Trabalho"},"tipo_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tipo Id"},"agregado_familiar":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agregado Familiar"},"creditos_ativos":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Creditos Ativos"},"mensalidade_casa":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mensalidade Casa"},"antiguidade_empresa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Antiguidade Empresa"},"mensalidade_creditos":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mensalidade Creditos"},"vencimento_liquido":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vencimento Liquido"},"foreign_nif":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Foreign Nif","description":"Foreign tax ID"}},"type":"object","required":["nome"],"title":"ClientCreate","description":"Client creation request."},"ClientResponse":{"properties":{"id":{"type":"integer","title":"Id"},"nome":{"type":"string","title":"Nome"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"contacto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contacto"},"nif":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Nif"},"cc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cc"},"validade_cc":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Validade Cc"},"entidade_emissora_cc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entidade Emissora Cc"},"particular":{"type":"boolean","title":"Particular","default":true},"recorrente":{"type":"boolean","title":"Recorrente","default":false},"carta_conducao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Carta Conducao"},"data_carta_conducao":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Data Carta Conducao"},"iban":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Iban"},"iban_alimentar":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Iban Alimentar"},"pais":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pais"},"morada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Morada"},"codigo_postal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codigo Postal"},"localidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localidade"},"cidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cidade"},"idcompany":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idcompany"},"id_pontodevenda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Pontodevenda"},"id_estado_civil":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Estado Civil"},"id_tipo_casa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Tipo Casa"},"id_contrato_trabalho":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Contrato Trabalho"},"tipo_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tipo Id"},"agregado_familiar":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agregado Familiar"},"creditos_ativos":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Creditos Ativos"},"mensalidade_casa":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mensalidade Casa"},"antiguidade_empresa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Antiguidade Empresa"},"mensalidade_creditos":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mensalidade Creditos"},"vencimento_liquido":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vencimento Liquido"},"foreign_nif":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Foreign Nif"},"addresses":{"items":{"$ref":"#/components/schemas/AddressResponse"},"type":"array","title":"Addresses"},"ID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id"},"Nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"NIF":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Nif"},"Contacto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contacto"},"CC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cc"},"ValidadeCC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validadecc"},"EntidadeEmissoraCC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entidadeemissoracc"},"CartaConducao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cartaconducao"},"DataCartaConducao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Datacartaconducao"}},"type":"object","required":["id","nome"],"title":"ClientResponse","description":"Client response with ID and addresses."},"ClientUpdate":{"properties":{"nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"contacto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contacto"},"nif":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Nif"},"cc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cc"},"validade_cc":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Validade Cc"},"entidade_emissora_cc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entidade Emissora Cc"},"particular":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Particular"},"recorrente":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Recorrente"},"carta_conducao":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Carta Conducao"},"data_carta_conducao":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Data Carta Conducao"},"iban":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Iban"},"iban_alimentar":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Iban Alimentar"},"pais":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pais"},"morada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Morada"},"codigo_postal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codigo Postal"},"localidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localidade"},"cidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cidade"},"id_pontodevenda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Pontodevenda"},"id_estado_civil":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Estado Civil"},"id_tipo_casa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Tipo Casa"},"id_contrato_trabalho":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Contrato Trabalho"},"tipo_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tipo Id"},"agregado_familiar":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Agregado Familiar"},"creditos_ativos":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Creditos Ativos"},"mensalidade_casa":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mensalidade Casa"},"antiguidade_empresa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Antiguidade Empresa"},"mensalidade_creditos":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mensalidade Creditos"},"vencimento_liquido":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vencimento Liquido"},"foreign_nif":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Foreign Nif"}},"type":"object","title":"ClientUpdate","description":"Client update request (all fields optional)."},"ClienteByIbanResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"ClienteByIbanResponse","description":"Response for IBAN lookup."},"ColorComboItem":{"properties":{"Id":{"type":"integer","title":"Id"},"Cor":{"type":"string","title":"Cor"}},"type":"object","required":["Id","Cor"],"title":"ColorComboItem","description":"Color dropdown item."},"CommissionDistributionBatchUpdate":{"properties":{"distributions":{"items":{"$ref":"#/components/schemas/CommissionDistributionCreate"},"type":"array","maxItems":6,"title":"Distributions","description":"List of commission distributions (max 6)"}},"type":"object","required":["distributions"],"title":"CommissionDistributionBatchUpdate","description":"Batch update all commission distributions for a contract."},"CommissionDistributionCreate":{"properties":{"user_id":{"type":"integer","title":"User Id","description":"Salesperson user ID (Z_Users.id)"},"valor_absoluto":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valor Absoluto","description":"Absolute commission value","default":"0"},"valor_percentual":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valor Percentual","description":"Percentage commission (0-100)","default":"0"}},"type":"object","required":["user_id"],"title":"CommissionDistributionCreate","description":"Commission distribution creation request."},"CommissionDistributionResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"contract_id":{"type":"integer","title":"Contract Id"},"user_id":{"type":"integer","title":"User Id"},"user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Name","description":"Salesperson full name"},"valor_absoluto":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Valor Absoluto"},"valor_percentual":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Valor Percentual"},"calculated_value":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Calculated Value","description":"Calculated commission amount"}},"type":"object","required":["ID","contract_id","user_id","valor_absoluto","valor_percentual"],"title":"CommissionDistributionResponse","description":"Commission distribution response with calculated values."},"CommissionDistributionUpdate":{"properties":{"user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"User Id"},"valor_absoluto":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valor Absoluto"},"valor_percentual":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valor Percentual"}},"type":"object","title":"CommissionDistributionUpdate","description":"Commission distribution update request (all fields optional)."},"ComprovativoBatchResponse":{"properties":{"file_group_id":{"type":"string","title":"File Group Id"},"attached":{"items":{"additionalProperties":{"type":"integer"},"type":"object"},"type":"array","title":"Attached"},"skipped":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Skipped"},"fornecedor_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedor Id"}},"type":"object","required":["file_group_id","attached","skipped"],"title":"ComprovativoBatchResponse","description":"Result of attaching ONE payment proof to a batch of movements."},"ContractCreate":{"properties":{"Cliente":{"type":"integer","title":"Cliente","description":"Client ID"},"Viatura":{"type":"integer","title":"Viatura","description":"Vehicle ID"},"Data":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data","description":"Contract date"},"Oferta1":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Oferta1"},"Oferta2":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Oferta2"},"Oferta3":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Oferta3"},"Oferta4":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Oferta4"},"Oferta5":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Oferta5"},"Oferta6":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Oferta6"},"ValorReserva":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valorreserva","description":"Reservation value"},"ValorVenda":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valorvenda","description":"Sale value"},"financiado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Financiado","description":"Is financed"},"temretoma":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Temretoma","description":"Has trade-in"},"kmretoma":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Kmretoma","description":"Trade-in km"},"valorretoma":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valorretoma","description":"Trade-in value"},"fornecedorretoma":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedorretoma","description":"Trade-in supplier ID"},"matricularetoma":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Matricularetoma"},"marcaretoma":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Marcaretoma"},"modeloretoma":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Modeloretoma"},"garantia":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Garantia","description":"Warranty ID"},"contratoproposta":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Contratoproposta","description":"Proposal contract ID"},"transportepara":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Transportepara"},"Fechado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fechado","description":"Is closed","default":false},"Comercial":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Comercial","description":"Salesperson ID"},"Datafecho":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafecho","description":"Closing date"},"Dataentrega":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataentrega","description":"Delivery date"},"Iva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Iva","description":"VAT percentage"},"FaturaID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Faturaid","description":"Invoice ID"},"IDempresa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idempresa","description":"Company ID (set server-side from auth)"},"IDpontodevenda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idpontodevenda","description":"Point of sale ID"},"IDestado":{"type":"integer","title":"Idestado","description":"State ID (1=open, 2=closed, 3=cancelled)","default":1},"ValoremFalta":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valoremfalta","description":"Missing value"},"Reservaate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Reservaate","description":"Reservation until date"},"idresponsavel":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idresponsavel","description":"Responsible user ID"},"meses_garantia":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Meses Garantia","description":"Warranty months"},"business_sale":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Business Sale","description":"Is a business sale (venda empresarial)"},"retomas":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Retomas","description":"List of vehicle IDs for trade-ins"}},"type":"object","required":["Cliente","Viatura"],"title":"ContractCreate","description":"Contract creation request."},"ContractDetailResponse":{"properties":{"contract":{"$ref":"#/components/schemas/ContractResponse"},"client":{"anyOf":[{"$ref":"#/components/schemas/ClientBlockResponse"},{"type":"null"}]},"vehicle":{"anyOf":[{"$ref":"#/components/schemas/VehicleBlockResponse"},{"type":"null"}]},"financial":{"anyOf":[{"$ref":"#/components/schemas/FinancialBlockResponse"},{"type":"null"}]},"pos":{"anyOf":[{"$ref":"#/components/schemas/POSBlockResponse"},{"type":"null"}]},"retomas":{"items":{"$ref":"#/components/schemas/RetomaResponse"},"type":"array","title":"Retomas"},"commissions":{"items":{"$ref":"#/components/schemas/CommissionDistributionResponse"},"type":"array","title":"Commissions"}},"type":"object","required":["contract","client","vehicle","financial","pos"],"title":"ContractDetailResponse","description":"Complete contract with all blocks."},"ContractListResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"ClienteNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Clientenome"},"ViaturaMatricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Viaturamatricula"},"Data":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data"},"ValorVenda":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valorvenda"},"Fechado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fechado"},"comissao_calculada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comissao Calculada"}},"type":"object","required":["ID","ClienteNome","ViaturaMatricula","Data","ValorVenda","Fechado","comissao_calculada"],"title":"ContractListResponse","description":"Contract list item (lighter response)."},"ContractResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Cliente":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cliente"},"ClienteNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Clientenome"},"Viatura":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viatura"},"ViaturaMatricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Viaturamatricula"},"Data":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data"},"ValorReserva":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valorreserva"},"ValorVenda":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valorvenda"},"Fechado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fechado"},"Datafecho":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafecho"},"IDestado":{"type":"integer","title":"Idestado"},"IDempresa":{"type":"integer","title":"Idempresa"},"IDpontodevenda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idpontodevenda"},"Comercial":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Comercial"},"idresponsavel":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idresponsavel"},"ResponsavelNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Responsavelnome"},"Oferta1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta1"},"Oferta2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta2"},"Oferta3":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta3"},"Oferta4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta4"},"Oferta5":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta5"},"Oferta6":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta6"},"garantia":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Garantia","description":"Warranty ID (Z_Warranties)"},"meses_garantia":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Meses Garantia","description":"Warranty duration in months"},"contratoproposta":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Contratoproposta","description":"Financing proposal ID"},"Dataentrega":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataentrega","description":"Delivery date"},"Reservaate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Reservaate","description":"Reservation until date"},"Iva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Iva","description":"VAT value"},"FaturaID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Faturaid","description":"Linked invoice ID"},"comissao_calculada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comissao Calculada","description":"Calculated commission"},"business_sale":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Business Sale","description":"Is a business sale"}},"type":"object","required":["ID","Cliente","ClienteNome","Viatura","ViaturaMatricula","Data","ValorReserva","ValorVenda","Fechado","Datafecho","IDestado","IDempresa","IDpontodevenda","Comercial"],"title":"ContractResponse","description":"Contract response with enriched data."},"ContractUpdate":{"properties":{"Cliente":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cliente"},"Viatura":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viatura"},"Data":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data"},"Oferta1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta1"},"Oferta2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta2"},"Oferta3":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta3"},"Oferta4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta4"},"Oferta5":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta5"},"Oferta6":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta6"},"ValorReserva":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valorreserva"},"ValorVenda":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valorvenda"},"financiado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Financiado"},"temretoma":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Temretoma"},"kmretoma":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Kmretoma"},"valorretoma":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valorretoma"},"fornecedorretoma":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedorretoma"},"matricularetoma":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricularetoma"},"marcaretoma":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marcaretoma"},"modeloretoma":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Modeloretoma"},"garantia":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Garantia"},"contratoproposta":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Contratoproposta"},"transportepara":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transportepara"},"Fechado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fechado"},"Comercial":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Comercial"},"Datafecho":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafecho"},"Dataentrega":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataentrega"},"Iva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Iva"},"FaturaID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Faturaid"},"IDpontodevenda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idpontodevenda"},"IDestado":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idestado"},"ValoremFalta":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valoremfalta"},"Reservaate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Reservaate"},"idresponsavel":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idresponsavel"},"meses_garantia":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Meses Garantia"},"business_sale":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Business Sale"},"retomas":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Retomas","description":"List of vehicle IDs for trade-ins"}},"type":"object","title":"ContractUpdate","description":"Contract update request (all fields optional)."},"ContratoTrabalhoComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"ContratoTrabalhoComboItem","description":"Contrato trabalho dropdown item."},"ConvertLeadBody":{"properties":{"name":{"type":"string","title":"Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"assign_to_self":{"type":"boolean","title":"Assign To Self","default":true}},"type":"object","required":["name"],"title":"ConvertLeadBody"},"CookieConsentPreferences":{"properties":{"necessary":{"type":"boolean","title":"Necessary","default":true},"analytics":{"type":"boolean","title":"Analytics","default":false},"marketing":{"type":"boolean","title":"Marketing","default":false}},"type":"object","title":"CookieConsentPreferences"},"CookieConsentRequest":{"properties":{"consent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Consent Id"},"preferences":{"$ref":"#/components/schemas/CookiePreferences"},"version":{"type":"string","title":"Version"}},"type":"object","required":["preferences","version"],"title":"CookieConsentRequest"},"CookieConsentResponse":{"properties":{"consent_id":{"type":"string","title":"Consent Id"},"version":{"type":"string","title":"Version"},"preferences":{"$ref":"#/components/schemas/CookiePreferences"}},"type":"object","required":["consent_id","version","preferences"],"title":"CookieConsentResponse"},"CookieConsentStatusResponse":{"properties":{"consent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Consent Id"},"version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version"},"preferences":{"anyOf":[{"$ref":"#/components/schemas/CookieConsentPreferences"},{"type":"null"}]}},"type":"object","title":"CookieConsentStatusResponse"},"CookiePreferences":{"properties":{"necessary":{"type":"boolean","title":"Necessary","default":true},"analytics":{"type":"boolean","title":"Analytics","default":false},"marketing":{"type":"boolean","title":"Marketing","default":false}},"type":"object","title":"CookiePreferences"},"CostCenterMovimentoCreate":{"properties":{"ValorTotal":{"type":"number","title":"Valortotal","description":"Can be negative (cost) or positive (profit)"},"ValorIva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valoriva","default":0},"Descrição":{"type":"string","title":"Descrição"},"Matrícula":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Matrícula"},"Fornecedor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedor"},"MétodoPagamento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Métodopagamento"},"NrFatura":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nrfatura"},"DataFatura":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafatura"},"Rubrica":{"type":"integer","title":"Rubrica"},"ATCUD":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Atcud","description":"Invoice ID (Faturas.ID) to link to this movement"},"lucro":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lucro","description":"Override lucro value (0 or 1). If None, backend auto-calculates based on vehicle status."},"cost_center_splits":{"items":{"$ref":"#/components/schemas/CostCenterSplitItem"},"type":"array","minItems":1,"title":"Cost Center Splits","description":"List of DESTINATION PV splits"},"Pago":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pago","description":"0 = parent registered but not yet paid, 1 = paid. When omitted, backend derives from MétodoPagamento."},"include_own_split":{"type":"boolean","title":"Include Own Split","description":"Also create a child movement in the ORIGIN PV for its own remaining share. Its value is derived by the backend from the total minus the destinations — never sent by the client.","default":false}},"type":"object","required":["ValorTotal","Descrição","Rubrica","cost_center_splits"],"title":"CostCenterMovimentoCreate","description":"Movement creation with cost center split.\n\nUnlike a regular movement, the parent's `Pago` flag is user-controlled\n(the dialog has a \"Pagamento efetuado\" checkbox that is independent of\nthe payment method): a cost-center parent must always declare a method\nso restitutions know how to refund, but the user may register the\nmovement before it is actually settled.\n\n`ValorTotal` may be negative (despesa split) or positive (receita split).\nThe effective direction is rubrica-governed at create (FluxoPositivo sign\nenforcement, like the plain create path) and then stored immutably on the\ngroup (`Z_MovimentoCentroCusto.direction`) — later edits can never flip it."},"CostCenterSplitDetail":{"properties":{"id":{"type":"integer","title":"Id"},"pv_id":{"type":"integer","title":"Pv Id"},"pv_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pv Name"},"value":{"type":"number","title":"Value"},"child_movimento_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Child Movimento Id"},"pago":{"type":"boolean","title":"Pago","default":false},"restitution_movimento_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Restitution Movimento Id"},"restitution_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Restitution Date"},"is_own_share":{"type":"boolean","title":"Is Own Share","default":false},"direction":{"type":"integer","title":"Direction","default":-1}},"type":"object","required":["id","pv_id","value"],"title":"CostCenterSplitDetail","description":"Detail of a single cost center split."},"CostCenterSplitItem":{"properties":{"pv_id":{"type":"integer","title":"Pv Id","description":"Target PV ID"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value","description":"Amount allocated to this PV (positive) - used in equal mode"},"percentage":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Percentage","description":"Percentage allocated to this PV - used in custom mode"}},"type":"object","required":["pv_id"],"title":"CostCenterSplitItem","description":"A single cost center split target."},"CostCenterSplitsUpdateRequest":{"properties":{"splits":{"items":{"$ref":"#/components/schemas/CostCenterSplitItem"},"type":"array","title":"Splits"},"new_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"New Total","description":"New parent movement total, sent as a positive magnitude. The backend re-applies the group's stored direction — the parent's side (receita/despesa) can never change here."},"include_own_split":{"type":"boolean","title":"Include Own Split","description":"Keep/create the origin PV's own share child movement.","default":false}},"type":"object","required":["splits"],"title":"CostCenterSplitsUpdateRequest","description":"Request body for updating cost center splits.\n\n`splits` carries DESTINATIONS only. The origin's own share is requested with\n`include_own_split` and its value is re-derived server-side as the remainder\n— omitting the flag on a group that has one removes it (when still unpaid)."},"CreateLinkRequest":{"properties":{"idcompany":{"type":"integer","title":"Idcompany"},"client_email":{"type":"string","format":"email","title":"Client Email"},"registration_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Registration Id"}},"type":"object","required":["idcompany","client_email"],"title":"CreateLinkRequest"},"CreditUsePayload":{"properties":{"amount":{"type":"number","exclusiveMinimum":0.0,"title":"Amount","description":"Amount of credits to use, e.g., 10.50"},"reason":{"type":"string","maxLength":100,"minLength":3,"title":"Reason"}},"type":"object","required":["amount","reason"],"title":"CreditUsePayload"},"CreditsResponse":{"properties":{"pv_id":{"type":"integer","title":"Pv Id","description":"Point of sale ID"},"credit_balance":{"type":"number","minimum":0.0,"title":"Credit Balance","description":"Credit balance in euros"},"last_billed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Billed At","description":"Last billing date"}},"type":"object","required":["pv_id","credit_balance"],"title":"CreditsResponse","description":"Credit balance response."},"DeletePayload":{"properties":{"ids":{"items":{"type":"integer"},"type":"array","title":"Ids"}},"type":"object","required":["ids"],"title":"DeletePayload"},"DeleteRequest":{"properties":{"path":{"type":"string","title":"Path"}},"type":"object","required":["path"],"title":"DeleteRequest"},"DocumentListItem":{"properties":{"ID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id","description":"NULL if document is 'em falta'"},"Nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"Tipodoc":{"type":"integer","title":"Tipodoc"},"tipo_doc_nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tipo Doc Nome"},"Data":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data"},"Byuser":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Byuser"},"pdf_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pdf Url"},"ID_doc_assinado":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Doc Assinado"},"url_doc_assinado":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url Doc Assinado"},"DataExpira":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataexpira"},"status":{"type":"string","title":"Status","description":"'carregado' or 'em falta'"},"status_assinado":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status Assinado","description":"'Por Assinar' if needs signature"},"id_modulo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Modulo"},"id_modulo_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Modulo Id"}},"type":"object","required":["Tipodoc","status"],"title":"DocumentListItem","description":"Lightweight model for document listing with status."},"DocumentListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DocumentListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"uploaded_count":{"type":"integer","title":"Uploaded Count","description":"Number of uploaded documents"},"missing_count":{"type":"integer","title":"Missing Count","description":"Number of missing suggested documents"}},"type":"object","required":["items","total","uploaded_count","missing_count"],"title":"DocumentListResponse","description":"Response for document listing."},"DocumentTypeResponse":{"properties":{"id":{"type":"integer","title":"Id"},"nome":{"type":"string","title":"Nome"},"modulo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Modulo"}},"type":"object","required":["id","nome"],"title":"DocumentTypeResponse","description":"Document type for dropdowns."},"DocumentTypesListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DocumentTypeResponse"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"DocumentTypesListResponse","description":"List of document types."},"DocumentUpdate":{"properties":{"nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"tipodoc":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tipodoc"},"data_expira":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Data Expira"},"id_doc_assinado":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Doc Assinado"}},"type":"object","title":"DocumentUpdate","description":"Input model for updating document metadata."},"DocumentUploadResponse":{"properties":{"id":{"type":"integer","title":"Id","description":"Document ID"},"pv_id":{"type":"integer","title":"Pv Id","description":"PV ID"},"id_declaracao":{"type":"integer","title":"Id Declaracao","description":"Declaration type ID"},"url":{"type":"string","title":"Url","description":"S3 URL to uploaded document"},"uploaded_at":{"type":"string","format":"date-time","title":"Uploaded At"}},"type":"object","required":["id","pv_id","id_declaracao","url"],"title":"DocumentUploadResponse","description":"Response for document upload."},"DoorsComboItem":{"properties":{"Id":{"type":"integer","title":"Id"},"Portas":{"type":"string","title":"Portas"}},"type":"object","required":["Id","Portas"],"title":"DoorsComboItem","description":"Doors (portas) dropdown item."},"DownloadRequest":{"properties":{"path":{"type":"string","title":"Path"},"expires_in":{"type":"integer","title":"Expires In","default":3600}},"type":"object","required":["path"],"title":"DownloadRequest"},"DrivingLicenseOcrResult":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"billed":{"type":"boolean","title":"Billed","default":false},"doc_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doc Type"},"confianca":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confianca"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","default":[]},"nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"numero_carta":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Numero Carta"},"data_emissao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Emissao"},"validade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validade"}},"type":"object","title":"DrivingLicenseOcrResult","description":"Result of POST /api/clients/ocr-driving-license (mirrors CitizenCardOcrResult):\nflat fields + success/error_message — an unreadable document is success=False,\nnever a 500. Data-minimized: no DOB, no nº de identificação civil (4d), no\nentidade emissora (4c), no categorias. Images are processed in memory and never\npersisted here; once the client is saved the frontend attaches them as Documentos\ndo cliente (módulo 12, tipo \"Carta de Condução\") via POST /documents-test/.\n\nUnlike the CC result, success already implies doc_type == \"carta_conducao\" —\na legible non-licence never reaches the caller as a success."},"DuplicateCheckLogRequest":{"properties":{"choice":{"type":"string","pattern":"^(shown|settle|continue)$","title":"Choice"},"candidate_count":{"type":"integer","maximum":10000.0,"minimum":0.0,"title":"Candidate Count"},"fornecedor_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedor Id"},"valor":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valor"}},"type":"object","required":["choice","candidate_count"],"title":"DuplicateCheckLogRequest","description":"Telemetry for the same-supplier/same-value unpaid check shown at insert.\n\nWithout this there is no way to tell, a month from now, whether the prompt\nreduced duplicates or merely trained everyone to click through it."},"EmailResponse":{"properties":{"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Email address"},"tipoemail":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tipoemail","description":"Email type (3=PV main, 4=Financial)"},"principal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Principal","description":"Is this the primary email","default":false},"ID":{"type":"integer","title":"Id","description":"Email ID"},"tipo_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tipo Email","description":"Human-readable email type"}},"type":"object","required":["ID"],"title":"EmailResponse","description":"Email response model."},"EncargoCreate":{"properties":{"entidade":{"type":"string","maxLength":255,"title":"Entidade","description":"Entity name (bank, leasing company, etc.)"},"referencia":{"type":"string","maxLength":255,"title":"Referencia","description":"Reference number/code"},"valor":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Valor","description":"Amount/value of the lien"},"marca":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Marca","description":"Additional notes/mark"}},"type":"object","required":["entidade","referencia","valor"],"title":"EncargoCreate","description":"Encargo (lien/charge) creation request."},"EncargoResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"idviatura":{"type":"integer","title":"Idviatura"},"entidade":{"type":"string","title":"Entidade"},"referencia":{"type":"string","title":"Referencia"},"valor":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Valor"},"marca":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marca"}},"type":"object","required":["ID","idviatura","entidade","referencia","valor"],"title":"EncargoResponse","description":"Encargo response with all fields."},"EncargoUpdate":{"properties":{"entidade":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Entidade"},"referencia":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Referencia"},"valor":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valor"},"marca":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Marca"}},"type":"object","title":"EncargoUpdate","description":"Encargo update request (all fields optional)."},"EnderecoResponse":{"properties":{"morada":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Morada","description":"Street address"},"codigopostal":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Codigopostal","description":"Postal code"},"localidade":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Localidade","description":"City"},"cidade":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Cidade","description":"City (alternative)"},"pais":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Pais","description":"Country"},"principal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Principal","description":"Is this the primary address","default":false},"ID":{"type":"integer","title":"Id","description":"Address ID"}},"type":"object","required":["ID"],"title":"EnderecoResponse","description":"Address response model."},"EstadoCivilComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"EstadoCivilComboItem","description":"Estado civil dropdown item."},"ExportRequest":{"properties":{"module":{"type":"string","title":"Module"},"filters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filters"},"columns":{"anyOf":[{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array"},{"type":"null"}],"title":"Columns"},"include_photos":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Include Photos","default":false}},"type":"object","required":["module"],"title":"ExportRequest","description":"Request body for export endpoint."},"ExportResponse":{"properties":{"download_url":{"type":"string","title":"Download Url"},"filename":{"type":"string","title":"Filename"},"record_count":{"type":"integer","title":"Record Count"}},"type":"object","required":["download_url","filename","record_count"],"title":"ExportResponse","description":"Response from export endpoint."},"FaturaUpdate":{"properties":{"A":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"A"},"B":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"B"},"C":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"C"},"D":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"D"},"E":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"E"},"F":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"F"},"G":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"G"},"H":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"H"},"I1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"I1"},"I2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I2"},"I3":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I3"},"I4":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I4"},"I5":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I5"},"I6":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I6"},"I7":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I7"},"I8":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I8"},"J1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"J1"},"J2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J2"},"J3":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J3"},"J4":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J4"},"J5":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J5"},"J6":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J6"},"J7":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J7"},"J8":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"J8"},"K1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K1"},"K2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K2"},"K3":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K3"},"K4":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K4"},"K5":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K5"},"K6":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K6"},"K7":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K7"},"K8":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"K8"},"L":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"L"},"M":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"M"},"N":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"N"},"O":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"O"},"P":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"P"},"Q":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"},"R":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"R"},"S":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"S"},"Descricao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Descricao"},"tipodocs":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tipodocs"},"Fechado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fechado"}},"type":"object","title":"FaturaUpdate","description":"Input model for updating an existing invoice."},"FinancialBlockResponse":{"properties":{"fatid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fatid","description":"Invoice ID or 'Em falta'"},"FaturaID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Faturaid"}},"type":"object","required":["FaturaID"],"title":"FinancialBlockResponse","description":"Financial/invoice data for contract."},"FolderRequest":{"properties":{"path":{"type":"string","title":"Path"}},"type":"object","required":["path"],"title":"FolderRequest"},"FuelTypeComboItem":{"properties":{"Id":{"type":"integer","title":"Id"},"Combustivel":{"type":"string","title":"Combustivel"}},"type":"object","required":["Id","Combustivel"],"title":"FuelTypeComboItem","description":"Fuel type dropdown item."},"GearboxComboItem":{"properties":{"Id":{"type":"integer","title":"Id"},"Caixa":{"type":"string","title":"Caixa"}},"type":"object","required":["Id","Caixa"],"title":"GearboxComboItem","description":"Gearbox dropdown item."},"GeneratePageRequest":{"properties":{"page_name":{"type":"string","title":"Page Name"},"slug":{"type":"string","title":"Slug"},"content_type_id":{"type":"integer","title":"Content Type Id"},"instructions":{"type":"string","title":"Instructions"}},"type":"object","required":["page_name","slug","content_type_id","instructions"],"title":"GeneratePageRequest"},"GeneratePageResponse":{"properties":{"job_id":{"type":"integer","title":"Job Id"},"status":{"type":"string","title":"Status"},"message":{"type":"string","title":"Message"}},"type":"object","required":["job_id","status","message"],"title":"GeneratePageResponse"},"GenerateWebsiteRequest":{"properties":{"domain":{"type":"string","title":"Domain"}},"type":"object","required":["domain"],"title":"GenerateWebsiteRequest"},"GenerateWebsiteResponse":{"properties":{"job_id":{"type":"integer","title":"Job Id"},"status":{"type":"string","title":"Status"},"message":{"type":"string","title":"Message"}},"type":"object","required":["job_id","status","message"],"title":"GenerateWebsiteResponse"},"GuaranteeComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"GuaranteeComboItem","description":"Guarantee dropdown item."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HistoryDTO":{"properties":{"id":{"type":"integer","title":"Id"},"user_id":{"type":"integer","title":"User Id"},"description":{"type":"string","title":"Description"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"event_type":{"type":"string","title":"Event Type"},"lead_id":{"type":"integer","title":"Lead Id"},"user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Name"}},"type":"object","required":["id","user_id","description","created_at","event_type","lead_id"],"title":"HistoryDTO"},"IdenticalMovement":{"properties":{"id":{"type":"integer","title":"Id"},"metodo_pagamento_id":{"type":"integer","title":"Metodo Pagamento Id"},"metodo_nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metodo Nome"},"ponto_venda_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ponto Venda Id"},"ponto_venda_nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ponto Venda Nome"},"reconciled":{"type":"string","title":"Reconciled"},"ignored":{"type":"boolean","title":"Ignored","default":false}},"type":"object","required":["id","metodo_pagamento_id","reconciled"],"title":"IdenticalMovement","description":"A movement with the same date, amount and full description as this one, sitting\nin a DIFFERENT conta of the same company. Informational only — two real accounts\ncan legitimately show the same line, so the UI states the fact and lets a human\ndecide. See list_bank_rows for why the match is cross-conta and description-exact."},"IdentifyRequest":{"properties":{"visitor_id":{"type":"string","title":"Visitor Id","description":"Visitor identifier to link"},"email":{"type":"string","title":"Email","description":"Visitor email address"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Visitor name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Visitor phone number"}},"type":"object","required":["visitor_id","email"],"title":"IdentifyRequest"},"IgnoreBulkPayload":{"properties":{"ids":{"items":{"type":"integer"},"type":"array","title":"Ids"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["ids","reason"],"title":"IgnoreBulkPayload"},"IgnorePayload":{"properties":{"reason":{"type":"string","title":"Reason"}},"type":"object","required":["reason"],"title":"IgnorePayload"},"ImportChecks":{"properties":{"parsed_debit_count":{"type":"integer","title":"Parsed Debit Count","default":0},"parsed_debit_total":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,16}|(?=[\\d.]{1,19}0*$)\\d{0,16}\\.\\d{0,2}0*$)","title":"Parsed Debit Total","default":0},"parsed_credit_count":{"type":"integer","title":"Parsed Credit Count","default":0},"parsed_credit_total":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,16}|(?=[\\d.]{1,19}0*$)\\d{0,16}\\.\\d{0,2}0*$)","title":"Parsed Credit Total","default":0},"computed_closing":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,16}|(?=[\\d.]{1,19}0*$)\\d{0,16}\\.\\d{0,2}0*$)"},{"type":"null"}],"title":"Computed Closing"},"counts_match":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Counts Match"},"totals_match":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Totals Match"},"balance_match":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Balance Match"}},"type":"object","title":"ImportChecks"},"ImportResult":{"properties":{"imported":{"type":"integer","title":"Imported"},"skipped":{"type":"integer","title":"Skipped","default":0},"skipped_existing":{"type":"integer","title":"Skipped Existing","default":0},"covered_until":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Covered Until"},"deferred_day":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Deferred Day"},"deferred_count":{"type":"integer","title":"Deferred Count","default":0},"statement_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Statement Id"},"statement":{"anyOf":[{"$ref":"#/components/schemas/StatementSummary"},{"type":"null"}]},"checks":{"anyOf":[{"$ref":"#/components/schemas/ImportChecks"},{"type":"null"}]},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","default":[]},"already_imported":{"type":"boolean","title":"Already Imported","default":false}},"type":"object","required":["imported"],"title":"ImportResult"},"IntegrazuAdvertCreate":{"properties":{"brand_id":{"type":"integer","title":"Brand Id","description":"Integrazu brand ID"},"model_id":{"type":"integer","title":"Model Id","description":"Integrazu model ID"},"fuel_id":{"type":"integer","title":"Fuel Id","description":"Integrazu fuel type ID"},"section_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Section Id","description":"Vehicle section ID (cars, motorcycles, etc.)"},"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Category Id","description":"Category ID (SUV, Sedan, etc.)"},"color_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Color Id","description":"Color ID"},"gearbox_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Id","description":"Gearbox type ID"},"gearbox_shift_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Shift Id","description":"Gearbox shift type ID"},"origin_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Origin Id","description":"Origin ID (national, imported)"},"capacity_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Capacity Id","description":"Seating capacity ID"},"doors_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Doors Id","description":"Door count ID"},"registration_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Registration Id","description":"Registration type ID"},"class_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Class Id","description":"Vehicle class ID"},"condition_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Condition Id","description":"Vehicle condition ID"},"traction_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Traction Id","description":"Traction type ID (FWD, RWD, AWD)"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id","description":"Specific version/trim ID"},"registration":{"type":"string","title":"Registration","description":"License plate / Registration number"},"vin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vin","description":"Vehicle Identification Number"},"version_designation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version Designation","description":"Version name/designation"},"mileage":{"type":"integer","title":"Mileage","description":"Mileage in kilometers"},"power":{"type":"integer","title":"Power","description":"Engine power in HP"},"engine_capacity":{"type":"integer","title":"Engine Capacity","description":"Engine capacity in cc"},"first_registration_year":{"type":"integer","title":"First Registration Year","description":"Year of first registration"},"first_registration_month":{"type":"integer","title":"First Registration Month","description":"Month of first registration (1-12)"},"price":{"type":"number","title":"Price","description":"Sale price"},"vendors_warranty_months":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vendors Warranty Months","description":"Vendor warranty in months","default":0},"inspection_valid_until":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inspection Valid Until","description":"Inspection valid until date (YYYY-MM-DD)"},"maker_warranty_valid_until_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Maker Warranty Valid Until Date","description":"Manufacturer warranty end date"},"maker_warranty_valid_until_km":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Maker Warranty Valid Until Km","description":"Manufacturer warranty km limit"},"co2_emissions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Co2 Emissions","description":"CO2 emissions (g/km)"},"iuc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Iuc","description":"Annual road tax (IUC)"},"max_fuel_range":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Max Fuel Range","description":"Maximum fuel range in km"},"urban_consumption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Urban Consumption","description":"Urban fuel consumption (L/100km)"},"extra_urban_consumption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Extra Urban Consumption","description":"Extra-urban consumption"},"combined_consumption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Combined Consumption","description":"Combined fuel consumption"},"max_speed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Max Speed","description":"Maximum speed (km/h)"},"metallic":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Metallic","description":"Metallic paint (1 or '')","default":""},"fixed_value":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Fixed Value","description":"Fixed price / No negotiation (1 or '')","default":""},"value_without_isv":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Value Without Isv","description":"Price without ISV tax (1 or '')","default":""},"accept_returns":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Accept Returns","description":"Accepts returns (1 or '')","default":""},"accept_funding":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Accept Funding","description":"Accepts financing (1 or '')","default":""},"classic":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Classic","description":"Classic vehicle (1 or '')","default":""},"damaged":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Damaged","description":"Damaged vehicle (1 or '')","default":""},"non_smoking":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Non Smoking","description":"Non-smoking vehicle (1 or '')","default":""},"particle_filter":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Particle Filter","description":"Has particle filter (1 or '')","default":""},"complete_review_book":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Complete Review Book","description":"Complete service book (1 or '')","default":""},"salvage":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Salvage","description":"Salvage vehicle (1 or '')","default":""},"second_key":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Second Key","description":"Has second key (1 or '')","default":""},"features":{"items":{"type":"integer"},"type":"array","title":"Features","description":"List of feature IDs"},"location_id":{"type":"string","title":"Location Id","description":"Dealership location ID"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Vehicle description text"},"video":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video","description":"Video URL"}},"type":"object","required":["brand_id","model_id","fuel_id","registration","mileage","power","engine_capacity","first_registration_year","first_registration_month","price","location_id"],"title":"IntegrazuAdvertCreate","description":"Complete model for creating a vehicle advert in Integrazu.\n\nIntegrazu uses catalog reference IDs for all vehicle attributes.\nBoolean flags use Union[int, str] to support both 1 or \"\" format.","example":{"accept_funding":1,"brand_id":12,"category_id":5,"color_id":10,"engine_capacity":1197,"features":[1,5,12,20],"first_registration_month":6,"first_registration_year":2017,"fuel_id":2,"gearbox_id":1,"location_id":"1","metallic":1,"mileage":50000,"model_id":345,"power":116,"price":25000.0,"registration":"AA-11-BB"}},"IntegrazuAdvertUpdate":{"properties":{"brand_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Brand Id"},"model_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Model Id"},"fuel_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fuel Id"},"section_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Section Id"},"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Category Id"},"color_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Color Id"},"gearbox_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Id"},"gearbox_shift_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Shift Id"},"origin_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Origin Id"},"capacity_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Capacity Id"},"doors_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Doors Id"},"registration_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Registration Id"},"class_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Class Id"},"condition_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Condition Id"},"traction_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Traction Id"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id"},"registration":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Registration"},"vin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vin"},"version_designation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version Designation"},"mileage":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mileage"},"power":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Power"},"engine_capacity":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Engine Capacity"},"first_registration_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"First Registration Year"},"first_registration_month":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"First Registration Month"},"price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Price"},"vendors_warranty_months":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vendors Warranty Months"},"inspection_valid_until":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inspection Valid Until"},"maker_warranty_valid_until_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Maker Warranty Valid Until Date"},"maker_warranty_valid_until_km":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Maker Warranty Valid Until Km"},"co2_emissions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Co2 Emissions"},"iuc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Iuc"},"max_fuel_range":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Max Fuel Range"},"urban_consumption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Urban Consumption"},"extra_urban_consumption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Extra Urban Consumption"},"combined_consumption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Combined Consumption"},"max_speed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Max Speed"},"metallic":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Metallic"},"fixed_value":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Fixed Value"},"value_without_isv":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Value Without Isv"},"accept_returns":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Accept Returns"},"accept_funding":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Accept Funding"},"classic":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Classic"},"damaged":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Damaged"},"non_smoking":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Non Smoking"},"particle_filter":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Particle Filter"},"complete_review_book":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Complete Review Book"},"salvage":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Salvage"},"second_key":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Second Key"},"features":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Features"},"location_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Id"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"video":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video"}},"type":"object","title":"IntegrazuAdvertUpdate","description":"Model for updating an existing Integrazu advert.\nAll fields are optional - only provide fields to update."},"IntegrazuImageUploadRequest":{"properties":{"images":{"items":{"type":"string"},"type":"array","title":"Images","description":"List of image URLs"}},"type":"object","required":["images"],"title":"IntegrazuImageUploadRequest","description":"Request body for uploading images to an advert.","example":{"images":["https://example.com/image1.jpg","https://example.com/image2.jpg"]}},"IntegrazuPublishRequest":{"properties":{"platform":{"type":"string","title":"Platform","description":"Platform name (standvirtual, olx, autosapo, etc.)"}},"type":"object","required":["platform"],"title":"IntegrazuPublishRequest","description":"Request body for publish/unpublish/republish operations.","example":{"platform":"standvirtual"}},"IntegrazuResult":{"properties":{"brands":{"items":{"$ref":"#/components/schemas/BrandActionResult"},"type":"array","title":"Brands"}},"type":"object","required":["brands"],"title":"IntegrazuResult","description":"Aggregated result of Integrazu operations."},"InteractionRequest":{"properties":{"dedupe_key":{"type":"string","title":"Dedupe Key"},"action":{"type":"string","title":"Action"}},"type":"object","required":["dedupe_key","action"],"title":"InteractionRequest"},"InvoiceCostCenterResponse":{"properties":{"invoice_id":{"type":"integer","title":"Invoice Id"},"total_value":{"type":"number","title":"Total Value"},"total_tax":{"type":"number","title":"Total Tax"},"splits":{"items":{"$ref":"#/components/schemas/InvoiceCostCenterSplitDetail"},"type":"array","title":"Splits"}},"type":"object","required":["invoice_id","total_value","total_tax","splits"],"title":"InvoiceCostCenterResponse","description":"Response for invoice cost center splits."},"InvoiceCostCenterSetRequest":{"properties":{"splits":{"items":{"$ref":"#/components/schemas/InvoiceCostCenterSplitItem"},"type":"array","minItems":1,"title":"Splits"},"mode":{"anyOf":[{"type":"string","pattern":"^(percentage|value)$"},{"type":"null"}],"title":"Mode","default":"percentage"}},"type":"object","required":["splits"],"title":"InvoiceCostCenterSetRequest","description":"Request body for setting invoice cost center splits.\nmode: 'percentage' (default) or 'value' — determines how splits are interpreted."},"InvoiceCostCenterSplitDetail":{"properties":{"id":{"type":"integer","title":"Id"},"pv_id":{"type":"integer","title":"Pv Id"},"pv_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pv Name"},"value":{"type":"number","title":"Value"},"tax":{"type":"number","title":"Tax"},"percentage":{"type":"number","title":"Percentage"}},"type":"object","required":["id","pv_id","value","tax","percentage"],"title":"InvoiceCostCenterSplitDetail","description":"Response detail for a single invoice cost center split."},"InvoiceCostCenterSplitItem":{"properties":{"pv_id":{"type":"integer","title":"Pv Id"},"percentage":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Percentage"},"value":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Value"}},"type":"object","required":["pv_id"],"title":"InvoiceCostCenterSplitItem","description":"A single invoice cost center split target (request).\nProvide either percentage or value. If both are given, value takes precedence."},"LicensePlateCodeItem":{"properties":{"country_name":{"type":"string","title":"Country Name"},"country_code":{"type":"string","title":"Country Code"}},"type":"object","required":["country_name","country_code"],"title":"LicensePlateCodeItem","description":"License plate country code item."},"LienCertificateResponse":{"properties":{"status":{"type":"string","title":"Status","description":"Status of the request (success/error)"},"reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference","description":"Reference number if successful"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message","description":"Error or status message"},"data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Data","description":"Additional data returned"}},"type":"object","required":["status"],"title":"LienCertificateResponse","description":"Response from external lien certificate API."},"ListRequest":{"properties":{"prefix":{"type":"string","title":"Prefix","default":""}},"type":"object","title":"ListRequest"},"ListingAdvertData":{"properties":{"make_id":{"type":"integer","title":"Make Id","description":"Make/brand ID (Integrazu: brand_id)"},"model_id":{"type":"integer","title":"Model Id","description":"Model ID (Integrazu: model_id)"},"fuel_id":{"type":"integer","title":"Fuel Id","description":"Fuel type ID (Integrazu: fuel_id)"},"type_id":{"type":"integer","title":"Type Id","description":"Vehicle type/category ID (Integrazu: category_id)"},"state_id":{"type":"integer","title":"State Id","description":"Vehicle condition ID (Integrazu: condition_id)"},"seats_id":{"type":"integer","title":"Seats Id","description":"Seats/capacity ID (Integrazu: capacity_id)"},"doors_id":{"type":"integer","title":"Doors Id","description":"Doors ID (Integrazu: doors_id)"},"transmission_id":{"type":"integer","title":"Transmission Id","description":"Transmission/gearbox ID (Integrazu: gearbox_id)"},"color_id":{"type":"integer","title":"Color Id","description":"Exterior color ID (Integrazu: color_id)"},"traction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Traction","description":"Traction type"},"mileage":{"type":"integer","title":"Mileage","description":"Kilometers (Integrazu: mileage)"},"engine_power":{"type":"integer","title":"Engine Power","description":"Engine power in HP (Integrazu: power)"},"engine_capacity":{"type":"integer","title":"Engine Capacity","description":"Engine capacity in cc (Integrazu: engine_capacity)"},"price":{"type":"number","title":"Price","description":"Sale price (Integrazu: price)"},"warranty_id":{"type":"integer","title":"Warranty Id","description":"Warranty months ID (Integrazu: vendors_warranty_months)","default":0},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id","description":"Version ID (Integrazu: version_id)"},"version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version","description":"Version/trim designation"},"interior_color_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Interior Color Id","description":"Interior color ID"},"toll_class":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Toll Class","description":"Toll class ID"},"gearbox_shift_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Shift Id","description":"Gearbox shift ID"},"gearbox_type_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Type Id","description":"Gearbox type ID"},"section_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Section Id","description":"Section ID"},"year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year","description":"First registration year"},"month":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Month","description":"First registration month 1-12"},"iuc_month":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Iuc Month","description":"IUC month"},"stand_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stand Id","description":"Stand ID"},"warranty_mileage":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Warranty Mileage","description":"Warranty km limit"},"co2_emissions":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Co2 Emissions","description":"CO2 emissions g/km"},"maximum_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Maximum Speed","description":"Maximum speed km/h"},"engine_torque":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Engine Torque","description":"Engine torque"},"performance_zero_hundred":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Performance Zero Hundred","description":"0-100 km/h time"},"urban_consumption":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Urban Consumption","description":"Urban consumption L/100km"},"extra_urban_consumption":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Extra Urban Consumption","description":"Extra-urban consumption"},"combined_consumption":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Combined Consumption","description":"Combined consumption"},"year_construction":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Year Construction","description":"Year of construction"},"number_cylinders":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Number Cylinders","description":"Number of cylinders"},"iuc_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Iuc Value","description":"Annual road tax IUC"},"stamp_tax":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Stamp Tax","description":"Stamp tax"},"credit_down_payment":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Credit Down Payment","description":"Credit down payment"},"semi_trucks_body":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Semi Trucks Body","description":"Semi truck body"},"importation_isv":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Importation Isv","description":"ISV importation"},"importation_transport":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Importation Transport","description":"Transport importation cost"},"importation_legal_costs":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Importation Legal Costs","description":"Legal costs importation"},"active":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Active","description":"Active 1/0"},"sold":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sold","description":"Sold 1/0"},"reserved":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reserved","description":"Reserved 1/0"},"by_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"By Order","description":"By order 1/0"},"available_soon":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Available Soon","description":"Available soon 1/0"},"approved":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Approved","description":"Approved 1/0"},"metallic":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Metallic","description":"Metallic paint 1/0"},"accept_returns":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Accept Returns","description":"Accepts returns 1/0"},"financing_possibility":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Financing Possibility","description":"Accepts financing 1/0"},"promotion_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Promotion Price","description":"Promotion price 1/0"},"commercial":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Commercial","description":"Commercial vehicle 1/0"},"without_iva":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Without Iva","description":"Without IVA 1/0"},"without_isv":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Without Isv","description":"Without ISV 1/0"},"second_key":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Second Key","description":"Has second key 1/0"},"manuals":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Manuals","description":"Has manuals/service book 1/0"},"export_vin":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Vin","description":"Export VIN 1/0"},"license_plate_export":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"License Plate Export","description":"Export license plate 1/0"},"importation_legalization":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Importation Legalization","description":"Legalization 1/0"},"credit_month_payment":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credit Month Payment","description":"Credit month payment"},"life_insurance":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Life Insurance","description":"Life insurance 1/0"},"export_easysite":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Easysite","description":"Export to easysite 1/0"},"export_portals":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Portals","description":"Export to portals 1/0"},"export_carmine":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Carmine","description":"Export to Carmine 1/0"},"export_standvirtual":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Standvirtual","description":"Export to StandVirtual 1/0"},"active_standvirtual":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Active Standvirtual","description":"Active on StandVirtual 1/0"},"renew_standvirtual":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Renew Standvirtual","description":"Renew on StandVirtual 1/0"},"export_olx":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Olx","description":"Export to OLX 1/0"},"renew_olx":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Renew Olx","description":"Renew on OLX 1/0"},"export_autosapo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Autosapo","description":"Export to AutoSapo 1/0"},"active_autosapo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Active Autosapo","description":"Active on AutoSapo 1/0"},"export_hellocar":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Hellocar","description":"Export to HelloCar 1/0"},"active_hellocar":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Active Hellocar","description":"Active on HelloCar 1/0"},"renew_hellocar":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Renew Hellocar","description":"Renew on HelloCar 1/0"},"export_piscapisca":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Piscapisca","description":"Export to PiscaPisca 1/0"},"active_piscapisca":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Active Piscapisca","description":"Active on PiscaPisca 1/0"},"renew_piscapisca":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Renew Piscapisca","description":"Renew on PiscaPisca 1/0"},"export_custojusto":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Custojusto","description":"Export to CustoJusto 1/0"},"active_custojusto":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Active Custojusto","description":"Active on CustoJusto 1/0"},"export_seucarro":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Export Seucarro","description":"Export to SeuCarro 1/0"},"negotiable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Negotiable","description":"Price negotiable"},"iva_deductible":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Iva Deductible","description":"Tax deductible"},"iva_discriminated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Iva Discriminated","description":"Tax itemized"},"destaque":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Destaque","description":"Featured/highlighted"},"classic":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Classic","description":"Classic vehicle"},"damaged":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Damaged","description":"Damaged vehicle"},"non_smoking":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Non Smoking","description":"Non-smoking vehicle"},"particle_filter":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Particle Filter","description":"Has particle filter"},"salvage":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Salvage","description":"Salvage vehicle"},"brand_program_edp":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Brand Program Edp","description":"EDP brand program"},"license_plate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Plate","description":"License plate"},"registrations":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Registrations","description":"Registration type"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Origin","description":"Origin"},"vin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vin","description":"VIN"},"video_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video Url","description":"Video URL"},"observations":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Observations","description":"Vehicle description"},"observations_english":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Observations English","description":"English description"},"tag_img":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag Img","description":"Image tag"},"inspection_expiration":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inspection Expiration","description":"Inspection valid until"},"warranty_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Warranty Date","description":"Warranty end date"},"maintenance_history":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Maintenance History","description":"Maintenance history"},"hashtag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hashtag","description":"Hashtag"},"reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference","description":"Reference"},"supplier_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Supplier Type","description":"Supplier type"},"monthly_amount":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Monthly Amount","description":"Monthly amount"},"rpm":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rpm","description":"RPM"},"sold_to_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sold To City","description":"Sold to city"},"sold_to_district":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sold To District","description":"Sold to district"},"date_campaigns":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Campaigns","description":"Campaign dates"},"max_fuel_range":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Max Fuel Range","description":"Max fuel range km"},"credit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit","description":"Credit info"},"credit_tan_value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Tan Value","description":"Credit TAN value"},"credit_taeg_value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Taeg Value","description":"Credit TAEG value"},"credit_mtic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Mtic","description":"Credit MTIC"},"credit_cpp":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Cpp","description":"Credit CPP"},"credit_cac":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Cac","description":"Credit CAC"},"credit_financial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Financial","description":"Credit financial"},"credit_legal_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Legal Text","description":"Credit legal text"},"credit_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Date","description":"Credit date"},"semi_trucks_bed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Semi Trucks Bed","description":"Semi truck bed"},"semi_trucks_height":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Semi Trucks Height","description":"Semi truck height"},"semi_trucks_length":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Semi Trucks Length","description":"Semi truck length"},"semi_trucks_suspension":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Semi Trucks Suspension","description":"Semi truck suspension"},"semi_trucks_load":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Semi Trucks Load","description":"Semi truck load"},"text_campaigns":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text Campaigns","description":"Campaign text"},"equipments":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Equipments","description":"Equipment IDs comma-separated"},"batery_type":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Batery Type","description":"Battery type ID"},"wltp_autonomy":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Wltp Autonomy","description":"WLTP autonomy km"},"autonomy":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Autonomy","description":"Autonomy km"},"battery_type_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Battery Type Id","description":"Battery type ID"},"brake_energy_recovery_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Brake Energy Recovery Id","description":"Brake energy recovery ID"},"charging_connector_type_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Charging Connector Type Id","description":"Charging connector type ID"},"type_of_current_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Type Of Current Id","description":"Type of current ID"},"number_charging_cycles":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Number Charging Cycles","description":"Number of charging cycles"},"number_batteries":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Number Batteries","description":"Number of batteries"},"number_engines":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Number Engines","description":"Number of engines"},"electric_power_peak":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Electric Power Peak","description":"Electric power peak"},"battery_condition":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Battery Condition","description":"Battery condition"},"hybrid_system_power_hp":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Hybrid System Power Hp","description":"Hybrid system power HP"},"charging_time_100":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Charging Time 100","description":"Charging time to 100%"},"charging_time_80":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Charging Time 80","description":"Charging time to 80%"},"charging_time_home":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Charging Time Home","description":"Charging time at home"},"max_charging_power":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Charging Power","description":"Max charging power"},"battery_capacity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Battery Capacity","description":"Battery capacity"},"avg_consumption":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Consumption","description":"Average consumption"},"license_plate_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Plate Date","description":"License plate date"}},"additionalProperties":true,"type":"object","required":["make_id","model_id","fuel_id","type_id","state_id","seats_id","doors_id","transmission_id","color_id","mileage","engine_power","engine_capacity","price"],"title":"ListingAdvertData","description":"Listing advert data matching ViaturasEasyDataGreen table schema.\n\nREQUIRED fields (for Integrazu):\n- make_id (brand_id), model_id, fuel_id, type_id (category_id)\n- color_id, transmission_id (gearbox_id), seats_id (capacity_id)\n- doors_id, state_id (condition_id), traction\n- version_id OR version (one required)\n- mileage, engine_power, engine_capacity, price\n- warranty_id (can be 0)\n\nAll types match SQL Server column types."},"ListingSaveRequest":{"properties":{"listing_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Listing Id","description":"ViaturasEasyDataGreen.ID - if null, creates new listing"},"vehicle_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vehicle Id","description":"Viatura.ID - used when creating new listing from vehicle"},"listing_data":{"additionalProperties":true,"type":"object","title":"Listing Data","description":"Listing data matching ViaturasEasyDataGreen columns"},"brands":{"anyOf":[{"items":{"$ref":"#/components/schemas/BrandExportConfig"},"type":"array"},{"type":"null"}],"title":"Brands","description":"List of brands with platforms to publish to. If empty/None, no Integrazu processing."},"website_ids":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Website Ids","description":"List of Websites.id to export listing to (Z_WebsiteExports)"},"image_urls":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Image Urls","description":"List of image URLs to upload to Integrazu"}},"type":"object","required":["listing_data"],"title":"ListingSaveRequest","description":"Request body for POST /listings/save\n\nIf listing_id is provided, updates existing listing.\nIf listing_id is null/None, creates a new listing.\nOptionally handles Integrazu integration for brands with platforms."},"ListingSaveResponse":{"properties":{"listing_id":{"type":"integer","title":"Listing Id"},"listing_saved":{"type":"boolean","title":"Listing Saved"},"integrazu":{"anyOf":[{"$ref":"#/components/schemas/IntegrazuResult"},{"type":"null"}]},"website_exports_created":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Website Exports Created"},"website_exports_removed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Website Exports Removed"}},"type":"object","required":["listing_id","listing_saved"],"title":"ListingSaveResponse","description":"Response for PUT /listings/{listing_id}/save","example":{"integrazu":{"brands":[{"action":"job_started","brand_id":5,"job_id":123,"platforms_to_publish":["carmine","standvirtual"],"reason":"no_advert_exists"},{"action":"update_sent","brand_id":8,"reason":"all_platforms_already_published"}]},"listing_id":925,"listing_saved":true,"website_exports_created":2,"website_exports_removed":1}},"ManualGenerateRequest":{"properties":{"company_name":{"type":"string","title":"Company Name"},"company_description":{"type":"string","title":"Company Description"},"company_slogan":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Slogan"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"primary_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Color"},"secondary_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secondary Color"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"},"facebook_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Facebook Url"},"instagram_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instagram Url"},"linkedin_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Url"},"core_values":{"items":{"type":"string"},"type":"array","title":"Core Values","default":[]},"mission_statement":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mission Statement"},"services":{"items":{"$ref":"#/components/schemas/ServiceItem"},"type":"array","title":"Services","default":[]},"unique_selling_points":{"items":{"type":"string"},"type":"array","title":"Unique Selling Points","default":[]},"warranties":{"items":{"type":"string"},"type":"array","title":"Warranties","default":[]},"target_audience":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Audience"},"company_story":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Story"},"trust_signals":{"anyOf":[{"$ref":"#/components/schemas/TrustSignals"},{"type":"null"}]},"customer_benefits":{"items":{"type":"string"},"type":"array","title":"Customer Benefits","default":[]},"key_messages":{"items":{"type":"string"},"type":"array","title":"Key Messages","default":[]},"tone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tone","default":"professional"}},"type":"object","required":["company_name","company_description"],"title":"ManualGenerateRequest","description":"Manual website generation without scraping - user provides all info."},"MetodoPagamento":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"MetodoPagamento"},"ModelComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"ModelComboItem","description":"Model dropdown item."},"ModifyPageRequest":{"properties":{"instructions":{"type":"string","title":"Instructions"}},"type":"object","required":["instructions"],"title":"ModifyPageRequest"},"ModifyPageResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"page_id":{"type":"integer","title":"Page Id"},"slug":{"type":"string","title":"Slug"},"blocks_updated":{"type":"integer","title":"Blocks Updated"},"message":{"type":"string","title":"Message"}},"type":"object","required":["success","page_id","slug","blocks_updated","message"],"title":"ModifyPageResponse"},"MoveRequest":{"properties":{"source":{"type":"string","title":"Source"},"destination":{"type":"string","title":"Destination"}},"type":"object","required":["source","destination"],"title":"MoveRequest"},"MovementInvoiceLink":{"properties":{"fatura_id":{"type":"integer","title":"Fatura Id","description":"Faturas.ID"},"amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Amount","description":"Valor alocado a esta fatura (positivo). Vazio = valor total do movimento."}},"type":"object","required":["fatura_id"],"title":"MovementInvoiceLink","description":"One invoice allocated to a movement.\n\n`amount` is a POSITIVE magnitude; the direction comes from the movement's\nown sign. None means \"this movement's full value\" — the convention the\nbackfilled one-to-one links use, which is what keeps the justification\naggregate byte-identical for existing data. (Note this is the OPPOSITE of\nreconciliations.amount, where NULL means the whole INVOICE.)"},"MovementInvoicesRequest":{"properties":{"links":{"items":{"$ref":"#/components/schemas/MovementInvoiceLink"},"type":"array","title":"Links","description":"Conjunto completo de faturas associadas. Lista vazia remove todas."}},"type":"object","title":"MovementInvoicesRequest","description":"Replace a movement's whole invoice set (#763)."},"MovementTransferPvRequest":{"properties":{"to_point_of_sale_id":{"type":"integer","exclusiveMinimum":0.0,"title":"To Point Of Sale Id","description":"Ponto de venda que passa a ser dono do movimento"}},"type":"object","required":["to_point_of_sale_id"],"title":"MovementTransferPvRequest","description":"Hand an unpaid movement over to another point of sale of the same company.\n\nOnly the DESTINATION is client-supplied: the origin is always the caller's own\npoint of sale, enforced in the UPDATE's WHERE clause."},"MovimentoCreate":{"properties":{"ValorTotal":{"type":"number","title":"Valortotal","description":"Can be negative (cost) or positive (profit)"},"ValorIva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valoriva","default":0},"Descrição":{"type":"string","title":"Descrição"},"Matrícula":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Matrícula"},"Fornecedor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedor"},"MétodoPagamento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Métodopagamento"},"NrFatura":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nrfatura"},"DataFatura":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafatura"},"Rubrica":{"type":"integer","title":"Rubrica"},"ATCUD":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Atcud","description":"Invoice ID (Faturas.ID) to link to this movement"},"lucro":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lucro","description":"Override lucro value (0 or 1). If None, backend auto-calculates based on vehicle status."}},"type":"object","required":["ValorTotal","Descrição","Rubrica"],"title":"MovimentoCreate","description":"User-provided fields for movement creation.\nSystem-managed fields (Pago, main, DataPagamento) are set by backend.\nATCUD is allowed to link an existing invoice to the movement.\nlucro is optional - if provided, it overrides backend auto-calculation."},"MovimentoDetailedResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"ValorTotal":{"type":"number","title":"Valortotal"},"ValorIva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valoriva"},"Descrição":{"type":"string","title":"Descrição"},"Matrícula":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Matrícula"},"Fornecedor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedor"},"MétodoPagamento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Métodopagamento"},"Pago":{"type":"boolean","title":"Pago"},"DataPagamento":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datapagamento"},"NrFatura":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nrfatura"},"DataFatura":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafatura"},"Rubrica":{"type":"integer","title":"Rubrica"},"ATCUD":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Atcud"},"IgnoraAtcud":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ignoraatcud"},"main":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Main"},"lucro":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Lucro"},"DataRegisto":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataregisto"},"RubricaDescricao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rubricadescricao"},"ViaturaMatricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Viaturamatricula"},"ViaturaID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viaturaid"},"MetodoPagamentoDescricao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metodopagamentodescricao"},"FaturaG":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Faturag"},"ClienteNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Clientenome"},"ClienteID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Clienteid"},"DocumentoID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Documentoid"},"DocumentoNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Documentonome"},"invoice_split_sync":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Invoice Split Sync"}},"type":"object","required":["ID","ValorTotal","ValorIva","Descrição","Matrícula","Fornecedor","MétodoPagamento","Pago","DataPagamento","NrFatura","DataFatura","Rubrica","ATCUD","IgnoraAtcud","main","lucro","DataRegisto","RubricaDescricao","ViaturaMatricula","ViaturaID","MetodoPagamentoDescricao","FaturaG","ClienteNome","ClienteID","DocumentoID"],"title":"MovimentoDetailedResponse"},"MovimentoListResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"ValorTotal":{"type":"number","title":"Valortotal"},"DataRegisto":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataregisto"},"DataPagamento":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datapagamento"},"Descrição":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Descrição"},"Descricao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Descricao"},"MetodoPagamentoDescricao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metodopagamentodescricao"},"ViaturaMatricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Viaturamatricula"},"ClienteNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Clientenome"},"RubricaDescricao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rubricadescricao"},"FaturaG":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Faturag"},"DocumentoID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Documentoid"},"ATCUD":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Atcud"},"Pago":{"type":"boolean","title":"Pago"},"lucro":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Lucro"},"RubricaID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rubricaid"},"FornecedorID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedorid"},"MetodoPagamentoID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Metodopagamentoid"},"ViaturaID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viaturaid"},"ClienteID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Clienteid"},"Matricula":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Matricula"},"PontoDeVenda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pontodevenda"}},"type":"object","required":["ID","ValorTotal","DataPagamento","Pago"],"title":"MovimentoListResponse"},"MovimentoSearchResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/MovimentoSearchResult"},"type":"array","title":"Results"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["results","total"],"title":"MovimentoSearchResponse"},"MovimentoSearchResult":{"properties":{"ID":{"type":"integer","title":"Id"},"ValorTotal":{"type":"number","title":"Valortotal"},"DataPagamento":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datapagamento"},"MetodoPagamento":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metodopagamento"},"Descrição":{"type":"string","title":"Descrição"},"DocumentoID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Documentoid"},"ViaturaMatricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Viaturamatricula"},"ClienteNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Clientenome"},"RubricaDesc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rubricadesc"},"lucro":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Lucro"},"FaturaStatus":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Faturastatus"},"ComprovativoStatus":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comprovativostatus"}},"type":"object","required":["ID","ValorTotal","DataPagamento","MetodoPagamento","Descrição","DocumentoID","ViaturaMatricula","ClienteNome","RubricaDesc","lucro","FaturaStatus","ComprovativoStatus"],"title":"MovimentoSearchResult"},"MovimentoUpdate":{"properties":{"ValorTotal":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valortotal"},"ValorIva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valoriva"},"Descrição":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Descrição"},"Matrícula":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Matrícula"},"Fornecedor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornecedor"},"MétodoPagamento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Métodopagamento"},"NrFatura":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nrfatura"},"DataFatura":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafatura"},"Rubrica":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rubrica"},"ATCUD":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Atcud"},"Pago":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pago"},"lucro":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lucro","description":"Override lucro (0 or 1). Sent only when the user explicitly confirms via the Lucros e Despesas prompt."}},"type":"object","title":"MovimentoUpdate"},"NifCheckResponse":{"properties":{"exists":{"type":"boolean","title":"Exists"},"client_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Client Id"},"client_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Name"},"is_foreign":{"type":"boolean","title":"Is Foreign","default":false}},"type":"object","required":["exists"],"title":"NifCheckResponse","description":"NIF duplicate check response."},"NoteCreate":{"properties":{"body":{"type":"string","maxLength":20000,"minLength":1,"title":"Body"},"title":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Title"},"priority":{"type":"integer","maximum":3.0,"minimum":0.0,"title":"Priority","default":0},"color":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Color"},"due_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Due At"},"pinned":{"type":"boolean","title":"Pinned","default":false},"id_modulo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Modulo"},"id_modulo_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Modulo Id"},"recipients":{"items":{"type":"integer"},"type":"array","title":"Recipients","default":[]},"reminder":{"anyOf":[{"$ref":"#/components/schemas/ReminderPayload"},{"type":"null"}]}},"type":"object","required":["body"],"title":"NoteCreate"},"NoteRequest":{"properties":{"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","title":"NoteRequest"},"NoteUpdate":{"properties":{"body":{"anyOf":[{"type":"string","maxLength":20000,"minLength":1},{"type":"null"}],"title":"Body"},"title":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Title"},"priority":{"anyOf":[{"type":"integer","maximum":3.0,"minimum":0.0},{"type":"null"}],"title":"Priority"},"color":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Color"},"due_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Due At"},"pinned":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pinned"},"is_archived":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Archived"},"id_modulo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Modulo"},"id_modulo_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Modulo Id"},"recipients":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Recipients"},"reminder":{"anyOf":[{"$ref":"#/components/schemas/ReminderPayload"},{"type":"null"}]}},"type":"object","title":"NoteUpdate","description":"Partial edit. Only fields the client actually sent are written, so an\nomitted `due_at` keeps its value while an explicit `null` clears it —\n`model_dump(exclude_unset=True)` is what separates the two.\n\n`recipients` and `reminder` are DESIRED STATE, not deltas: send the full\nlist the note should end up with and the server reconciles. Omit either to\nleave that overlay untouched; send `null` to clear it. This is what makes\nthe edit idempotent — see notes_db.update_note_composite."},"POSBlockResponse":{"properties":{"Desigancao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Desigancao"},"NomeComercial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nomecomercial"},"NIPC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nipc"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"NOMESOC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nomesoc"},"NIF":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nif"},"SWIFT":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Swift"},"MoradaSede":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Moradasede"},"CodPostSede":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codpostsede"},"IBANprincipal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ibanprincipal"},"LocalidadeSede":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localidadesede"},"CC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cc"},"Banco":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Banco"},"ValidadeCC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validadecc"},"PontosdeVendamorada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pontosdevendamorada"},"PontosdeVendaLocalidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pontosdevendalocalidade"},"PontosdeVendaCodPost":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pontosdevendacodpost"}},"type":"object","required":["Desigancao","NomeComercial","email","NOMESOC","SWIFT","MoradaSede","CodPostSede","IBANprincipal","LocalidadeSede","CC","Banco","ValidadeCC","PontosdeVendamorada","PontosdeVendaLocalidade","PontosdeVendaCodPost"],"title":"POSBlockResponse","description":"Point of sale data for contract."},"PartialSettlementRequest":{"properties":{"amount":{"type":"number","exclusiveMinimum":0.0,"title":"Amount","description":"Valor a liquidar agora (positivo)"},"payment_method_id":{"type":"integer","title":"Payment Method Id","description":"Conta / método de pagamento usado"}},"type":"object","required":["amount","payment_method_id"],"title":"PartialSettlementRequest","description":"Settle PART of a pending movement (#764 claim 2)."},"PartnerCreate":{"properties":{"utilizador_id":{"type":"integer","title":"Utilizador Id","description":"Utilizadores.ID — the user this partner record points at"},"valor_inicial":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Valor Inicial","description":"Initial value","default":"0"}},"type":"object","required":["utilizador_id"],"title":"PartnerCreate","description":"Body for POST /api/socios — submits a PARTNER_CREATE request."},"PartnerDetailResponse":{"properties":{"id":{"type":"integer","title":"Id"},"idcompany":{"type":"integer","title":"Idcompany"},"utilizador_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Utilizador Id","description":"NULL for paper sócios"},"nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome","description":"From Utilizadores.Nome or display_name"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"valor_inicial":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Valor Inicial"},"active":{"type":"boolean","title":"Active"},"agreements_count":{"type":"integer","title":"Agreements Count","description":"Currently-active agreements","default":0},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"agreements":{"items":{"$ref":"#/components/schemas/AgreementResponse"},"type":"array","title":"Agreements","default":[]}},"type":"object","required":["id","idcompany","valor_inicial","active"],"title":"PartnerDetailResponse","description":"GET /api/socios/{id} — partner + nested agreement history."},"PartnerMovimentoCreate":{"properties":{"ValorTotal":{"type":"number","title":"Valortotal","description":"Positive for deposit, negative for withdrawal"},"Descrição":{"type":"string","title":"Descrição","default":""},"MétodoPagamento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Métodopagamento"}},"type":"object","required":["ValorTotal"],"title":"PartnerMovimentoCreate","description":"Partner movement input - Rubrica is always 47, set by backend."},"PartnerResponse":{"properties":{"id":{"type":"integer","title":"Id"},"idcompany":{"type":"integer","title":"Idcompany"},"utilizador_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Utilizador Id","description":"NULL for paper sócios"},"nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome","description":"From Utilizadores.Nome or display_name"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"valor_inicial":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Valor Inicial"},"active":{"type":"boolean","title":"Active"},"agreements_count":{"type":"integer","title":"Agreements Count","description":"Currently-active agreements","default":0},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","idcompany","valor_inicial","active"],"title":"PartnerResponse","description":"Hydrated partner row for GET listings."},"PartnerUpdate":{"properties":{"valor_inicial":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Valor Inicial"},"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"}},"type":"object","title":"PartnerUpdate","description":"Body for PUT /api/socios/{id} — submits a PARTNER_UPDATE request."},"PaymentMethodSelectResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Método Pagamento":{"type":"string","title":"Método Pagamento"}},"type":"object","required":["ID","Método Pagamento"],"title":"PaymentMethodSelectResponse"},"PaymentStartPayload":{"properties":{"amount":{"type":"integer","minimum":1.0,"title":"Amount","description":"Amount to pay in EUR (integer)."},"method":{"type":"string","enum":["MBWAY","REFERENCE"],"title":"Method"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Required for MBWAY payments."}},"type":"object","required":["amount","method"],"title":"PaymentStartPayload"},"PaymentUpdateRequest":{"properties":{"movement_ids":{"items":{"type":"integer"},"type":"array","minItems":1,"title":"Movement Ids"},"payment_method_id":{"type":"integer","title":"Payment Method Id"}},"type":"object","required":["movement_ids","payment_method_id"],"title":"PaymentUpdateRequest"},"PendingApprover":{"properties":{"partner_id":{"type":"integer","title":"Partner Id"},"utilizador_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Utilizador Id"},"nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"}},"type":"object","required":["partner_id"],"title":"PendingApprover","description":"Lightweight shape for `approvers_pending` on a submit response —\njust identifies who still needs to vote, no vote/timestamp yet."},"PermissionAssign":{"properties":{"permission_id":{"type":"integer","title":"Permission Id"},"grant_privileged_role":{"type":"boolean","title":"Grant Privileged Role","default":false}},"type":"object","required":["permission_id"],"title":"PermissionAssign"},"PermissionCreate":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","required":["name"],"title":"PermissionCreate"},"PermissionUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","title":"PermissionUpdate"},"PermissionsBulkAssign":{"properties":{"permission_ids":{"items":{"type":"integer"},"type":"array","title":"Permission Ids"},"grant_privileged_role":{"type":"boolean","title":"Grant Privileged Role","default":false}},"type":"object","required":["permission_ids"],"title":"PermissionsBulkAssign"},"PointOfSaleComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"PointOfSaleComboItem","description":"Point of sale dropdown item."},"PontoVendaCreate":{"properties":{"Nome":{"type":"string","maxLength":255,"minLength":1,"title":"Nome","description":"Point of sale name"},"NomeComercial":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Nomecomercial","description":"Commercial name"},"DESIGANCAO":{"type":"string","maxLength":255,"minLength":1,"title":"Desigancao","description":"Business name/Designation"},"Contacto":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Contacto","description":"Contact phone"},"NIPC":{"type":"string","maxLength":50,"minLength":1,"title":"Nipc","description":"Tax ID for HQ"},"NIF":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Nif","description":"Partner tax ID"},"MORADASEDE":{"type":"string","maxLength":255,"minLength":1,"title":"Moradasede","description":"HQ address"},"CODPOSTSEDE":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Codpostsede","description":"HQ postal code"},"LOCALIDADESEDE":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Localidadesede","description":"HQ city"},"MORADA":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Morada","description":"Contact address"},"CODPOST":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Codpost","description":"Contact postal code"},"LOCALIDADE":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Localidade","description":"Contact city"},"EMAIL":{"type":"string","title":"Email","description":"Primary email address"},"EMAILFINANCEIRO":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Emailfinanceiro","description":"Financial email address"},"NOMESOC":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Nomesoc","description":"Partner/Shareholder name"},"CC":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Cc","description":"ID card number"},"VALIDADECC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validadecc","description":"ID card validity date"},"BANCO":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Banco","description":"Bank name"},"IBANPRINCIPAL":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ibanprincipal","description":"Primary IBAN"},"SWIFT":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Swift","description":"SWIFT code"},"TokenEasyData":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Tokeneasydata","description":"EasyData API token"},"IDeasydata":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Ideasydata","description":"EasyData ID"},"PassApp":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Passapp","description":"App password"},"Serie":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Serie","description":"Invoice series code"},"Scuts":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Scuts","description":"Highway tolls enabled","default":false},"CRM":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Crm","description":"CRM enabled","default":false},"LogoURL":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Logourl","description":"Logo URL"},"plan_id":{"type":"integer","title":"Plan Id","description":"Subscription plan ID"},"metodo_pagamento":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metodo Pagamento","description":"Payment method","default":"Banco"},"banco":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Banco","description":"Is bank payment method","default":false}},"type":"object","required":["Nome","DESIGANCAO","NIPC","MORADASEDE","EMAIL","plan_id"],"title":"PontoVendaCreate","description":"Create PV request - includes additional fields for business logic."},"PontoVendaListResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"},"DESIGANCAO":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Desigancao"},"Contacto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contacto"},"morada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Morada"},"codigopostal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codigopostal"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"NIPC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nipc"},"foto_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Foto Url"},"id_foto":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Foto"}},"type":"object","required":["ID","Nome","DESIGANCAO","Contacto","morada","codigopostal","email","NIPC","foto_url","id_foto"],"title":"PontoVendaListResponse","description":"PV list item (simplified for list endpoints)."},"PontoVendaListResponseWrapper":{"properties":{"items":{"items":{"$ref":"#/components/schemas/PontoVendaListResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total","description":"Total items in current page"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"}},"type":"object","required":["items","total","limit","offset"],"title":"PontoVendaListResponseWrapper","description":"Wrapped list response with pagination."},"PontoVendaResponse":{"properties":{"Nome":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Nome","description":"Point of sale name"},"NomeComercial":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Nomecomercial","description":"Commercial name"},"DESIGANCAO":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Desigancao","description":"Business name/Designation"},"Contacto":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Contacto","description":"Contact phone"},"NIPC":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Nipc","description":"Tax ID for HQ"},"NIF":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Nif","description":"Partner tax ID"},"MORADASEDE":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Moradasede","description":"HQ address"},"CODPOSTSEDE":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Codpostsede","description":"HQ postal code"},"LOCALIDADESEDE":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Localidadesede","description":"HQ city"},"MORADA":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Morada","description":"Contact address"},"CODPOST":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Codpost","description":"Contact postal code"},"LOCALIDADE":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Localidade","description":"Contact city"},"EMAIL":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Primary email address"},"EMAILFINANCEIRO":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Emailfinanceiro","description":"Financial email address"},"NOMESOC":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Nomesoc","description":"Partner/Shareholder name"},"CC":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Cc","description":"ID card number"},"VALIDADECC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validadecc","description":"ID card validity date"},"BANCO":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Banco","description":"Bank name"},"IBANPRINCIPAL":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ibanprincipal","description":"Primary IBAN"},"SWIFT":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Swift","description":"SWIFT code"},"TokenEasyData":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Tokeneasydata","description":"EasyData API token"},"IDeasydata":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Ideasydata","description":"EasyData ID"},"PassApp":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Passapp","description":"App password"},"Serie":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Serie","description":"Invoice series code"},"Scuts":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Scuts","description":"Highway tolls enabled","default":false},"CRM":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Crm","description":"CRM enabled","default":false},"LogoURL":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Logourl","description":"Logo URL"},"ID":{"type":"integer","title":"Id","description":"Point of sale ID"},"IDempresa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idempresa","description":"Company ID"},"credit_balance_cents":{"type":"integer","title":"Credit Balance Cents","description":"Credit balance in cents","default":0},"last_billed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Billed At","description":"Last billing date"},"PASSEMAIL":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Passemail","description":"Email password"},"IDezdata":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Idezdata","description":"EZData ID"},"Foto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Foto","description":"Photo URL"},"addresses":{"anyOf":[{"items":{"$ref":"#/components/schemas/EnderecoResponse"},"type":"array"},{"type":"null"}],"title":"Addresses"},"emails":{"anyOf":[{"items":{"$ref":"#/components/schemas/EmailResponse"},"type":"array"},{"type":"null"}],"title":"Emails"}},"type":"object","required":["ID"],"title":"PontoVendaResponse","description":"PV response model with database-generated fields."},"PontoVendaUpdate":{"properties":{"Nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"NomeComercial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nomecomercial"},"DESIGANCAO":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Desigancao"},"Contacto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contacto"},"NIPC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nipc"},"NIF":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nif"},"MORADASEDE":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Moradasede"},"CODPOSTSEDE":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codpostsede"},"LOCALIDADESEDE":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localidadesede"},"MORADA":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Morada"},"CODPOST":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codpost"},"LOCALIDADE":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localidade"},"EMAIL":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"EMAILFINANCEIRO":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Emailfinanceiro"},"NOMESOC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nomesoc"},"CC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cc"},"VALIDADECC":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validadecc"},"BANCO":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Banco"},"IBANPRINCIPAL":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ibanprincipal"},"SWIFT":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Swift"},"TokenEasyData":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tokeneasydata"},"IDeasydata":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ideasydata"},"PassApp":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Passapp"},"Serie":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serie"},"Scuts":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Scuts"},"CRM":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Crm"},"LogoURL":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logourl"}},"type":"object","title":"PontoVendaUpdate","description":"Update PV request - all fields optional."},"PublishJobCreateRequest":{"properties":{"vehicle_id":{"type":"integer","title":"Vehicle Id","description":"Viatura.ID - the vehicle to publish"},"pv_id":{"type":"integer","title":"Pv Id","description":"PontosDeVenda.ID - the point of sale (used for token lookup and ViaturasEasyDataGreen)"},"brands":{"items":{"$ref":"#/components/schemas/BrandPublishConfig"},"type":"array","title":"Brands","description":"List of brands to publish to, each with their platforms and website exports"},"listing_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Listing Id","description":"ViaturasEasyDataGreen.ID - if provided, uses existing listing instead of creating new one"},"listing_data":{"anyOf":[{"$ref":"#/components/schemas/ListingAdvertData"},{"type":"null"}],"description":"Listing data with ViaturasEasyDataGreen field names. Required if listing_id is not provided."},"image_urls":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Image Urls","description":"List of image URLs to upload. If not provided, uses photos from LocalizacaoFotos table."}},"type":"object","required":["vehicle_id","pv_id","brands"],"title":"PublishJobCreateRequest","description":"Request to start publishing workflow(s) for a vehicle - supports multiple brands.","example":{"brands":[{"brand_id":5,"platforms":["standvirtual","olx"],"renew":true,"website_ids":[1,2]},{"brand_id":8,"platforms":["carmine","autosapo_v2"],"renew":false,"website_ids":[3]}],"image_urls":["https://s3.../vehicle1.jpg","https://s3.../vehicle2.jpg"],"listing_data":{"color_id":2,"doors_id":5,"engine_capacity":1197,"engine_power":116,"fuel_id":16,"license_plate":"AA-00-BB","make_id":51,"mileage":35000,"model_id":2018,"month":6,"observations":"Viatura em excelente estado.","price":19500,"seats_id":89,"state_id":1,"traction":2,"transmission_id":1,"type_id":8,"version_id":86701,"warranty_id":0,"year":2020},"pv_id":10,"vehicle_id":1234}},"PublishJobCreateResponse":{"properties":{"jobs":{"items":{"$ref":"#/components/schemas/PublishJobCreatedInfo"},"type":"array","title":"Jobs"},"total_jobs":{"type":"integer","title":"Total Jobs"},"message":{"type":"string","title":"Message"}},"type":"object","required":["jobs","total_jobs","message"],"title":"PublishJobCreateResponse","description":"Response after creating publishing jobs (one per brand).","example":{"jobs":[{"brand_id":5,"brand_name":"Stand ABC","job_id":123,"platforms":["standvirtual","olx"],"status":"pending"},{"brand_id":8,"brand_name":"Stand XYZ","job_id":124,"platforms":["carmine"],"status":"pending"}],"message":"2 publicacoes iniciadas. Use os job_ids para verificar o progresso.","total_jobs":2}},"PublishJobCreatedInfo":{"properties":{"job_id":{"type":"integer","title":"Job Id"},"brand_id":{"type":"integer","title":"Brand Id"},"brand_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Name"},"platforms":{"items":{"type":"string"},"type":"array","title":"Platforms"},"status":{"type":"string","title":"Status","default":"pending"}},"type":"object","required":["job_id","brand_id","platforms"],"title":"PublishJobCreatedInfo","description":"Info about a single created job."},"PublishJobListResponse":{"properties":{"jobs":{"items":{"$ref":"#/components/schemas/PublishJobSummaryResponse"},"type":"array","title":"Jobs"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["jobs","total"],"title":"PublishJobListResponse","description":"List of publishing jobs for a vehicle."},"PublishJobResponse":{"properties":{"id":{"type":"integer","title":"Id"},"idcompany":{"type":"integer","title":"Idcompany"},"vehicle_id":{"type":"integer","title":"Vehicle Id"},"brand_id":{"type":"integer","title":"Brand Id"},"pv_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pv Id"},"integrazu_advert_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Integrazu Advert Id"},"status":{"type":"string","title":"Status"},"progress":{"type":"integer","title":"Progress"},"current_step":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Step"},"target_platforms":{"items":{"type":"string"},"type":"array","title":"Target Platforms"},"platforms_succeeded":{"type":"integer","title":"Platforms Succeeded"},"platforms_failed":{"type":"integer","title":"Platforms Failed"},"platforms_total":{"type":"integer","title":"Platforms Total"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"steps":{"items":{"$ref":"#/components/schemas/PublishJobStepResponse"},"type":"array","title":"Steps","default":[]},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["id","idcompany","vehicle_id","brand_id","status","progress","target_platforms","platforms_succeeded","platforms_failed","platforms_total","created_at","updated_at"],"title":"PublishJobResponse","description":"Publishing job status response."},"PublishJobStepResponse":{"properties":{"id":{"type":"integer","title":"Id"},"step_type":{"type":"string","title":"Step Type"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"step_order":{"type":"integer","title":"Step Order"},"status":{"type":"string","title":"Status"},"display_name":{"type":"string","title":"Display Name"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code"},"response_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Response Data"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Ms"},"retry_count":{"type":"integer","title":"Retry Count","default":0}},"type":"object","required":["id","step_type","step_order","status","display_name"],"title":"PublishJobStepResponse","description":"Individual step status within a publishing job."},"PublishJobSummaryResponse":{"properties":{"id":{"type":"integer","title":"Id"},"vehicle_id":{"type":"integer","title":"Vehicle Id"},"status":{"type":"string","title":"Status"},"progress":{"type":"integer","title":"Progress"},"current_step":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Step"},"platforms_succeeded":{"type":"integer","title":"Platforms Succeeded"},"platforms_failed":{"type":"integer","title":"Platforms Failed"},"platforms_total":{"type":"integer","title":"Platforms Total"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["id","vehicle_id","status","progress","platforms_succeeded","platforms_failed","platforms_total","created_at"],"title":"PublishJobSummaryResponse","description":"Lightweight job summary for list views."},"PvRoleAssign":{"properties":{"idrole":{"type":"integer","title":"Idrole"},"idpointofsale":{"type":"integer","title":"Idpointofsale"}},"type":"object","required":["idrole","idpointofsale"],"title":"PvRoleAssign"},"PvRolesBulkAssign":{"properties":{"assignments":{"items":{"$ref":"#/components/schemas/PvRoleAssign"},"type":"array","title":"Assignments"}},"type":"object","required":["assignments"],"title":"PvRolesBulkAssign"},"PvRosterReplaceRequest":{"properties":{"idpointofsale":{"type":"integer","title":"Idpointofsale"},"inicio":{"type":"string","format":"date","title":"Inicio"},"rows":{"items":{"$ref":"#/components/schemas/PvRosterRow"},"type":"array","title":"Rows"}},"type":"object","required":["idpointofsale","inicio"],"title":"PvRosterReplaceRequest","description":"Body for POST /api/socios/pv-roster.\n\nCloses all currently-active agreements at `idpointofsale` (fim = inicio - 1 day)\nand inserts a new agreement per row, all in one transaction once approved."},"PvRosterRow":{"properties":{"partner_id":{"type":"integer","title":"Partner Id"},"percentagem":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Percentagem"}},"type":"object","required":["partner_id","percentagem"],"title":"PvRosterRow","description":"One partner's seat in the proposed new roster."},"QRInvoiceItem":{"properties":{"A":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"A"},"B":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"B"},"D":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"D"},"F":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"F"},"G":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"G"},"H":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"H"},"I7":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I7"},"I8":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I8"},"N":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"N"},"O":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"O"},"P":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"P"},"raw_qr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Raw Qr"},"already_exists":{"type":"boolean","title":"Already Exists","default":false},"success":{"type":"boolean","title":"Success","default":true}},"type":"object","title":"QRInvoiceItem","description":"One invoice parsed from a single QR code.\n\nPopulated for every distinct QR found in a document so the frontend can\nqueue them (a statement may bundle several invoices, each its own QR/ATCUD).\nIncludes `D` (doc type) so per-item doc-type mapping works in queue mode, and\n`already_exists` so a QR whose ATCUD is already stored is flagged rather than\nsilently dropped."},"QRProcessResult":{"properties":{"A":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"A"},"B":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"B"},"F":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"F"},"G":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"G"},"H":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"H"},"I7":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I7"},"I8":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I8"},"N":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"N"},"O":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"O"},"P":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"P"},"raw_qr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Raw Qr"},"success":{"type":"boolean","title":"Success","default":true},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"invoices":{"anyOf":[{"items":{"$ref":"#/components/schemas/QRInvoiceItem"},"type":"array"},{"type":"null"}],"title":"Invoices"}},"type":"object","title":"QRProcessResult","description":"Result from QR code processing."},"ReconciliationInvoice":{"properties":{"fatura_id":{"type":"integer","title":"Fatura Id"},"numero":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Numero"},"total":{"type":"number","title":"Total"},"allocated_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Allocated Amount"},"nif":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nif"},"data_documento":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data Documento"},"emitente":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Emitente"}},"type":"object","required":["fatura_id","total"],"title":"ReconciliationInvoice"},"ReminderPayload":{"properties":{"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel","default":"inapp"},"next_fire_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Fire At"},"recurrence_unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recurrence Unit"},"recurrence_interval":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":1.0},{"type":"null"}],"title":"Recurrence Interval"},"snoozed_until":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snoozed Until"}},"type":"object","title":"ReminderPayload"},"ResendRequest":{"properties":{"client_email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Client Email"}},"type":"object","title":"ResendRequest"},"ResumeGenerationRequest":{"properties":{"stage":{"type":"string","title":"Stage"},"core_values":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Core Values"},"theme_edits":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Theme Edits"},"page_plans":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Page Plans"}},"type":"object","required":["stage"],"title":"ResumeGenerationRequest","description":"User's edits at a wizard pause point."},"RetomaResponse":{"properties":{"idretoma":{"type":"integer","title":"Idretoma"},"id_contrato":{"type":"integer","title":"Id Contrato"},"id_viatura":{"type":"integer","title":"Id Viatura"},"Preco":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Preco"},"matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula"}},"type":"object","required":["idretoma","id_contrato","id_viatura","Preco","matricula"],"title":"RetomaResponse","description":"Trade-in vehicle data."},"RoleCreate":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"idcompany":{"type":"integer","title":"Idcompany"}},"type":"object","required":["name","idcompany"],"title":"RoleCreate"},"RoleModules":{"properties":{"modules":{"items":{"type":"string"},"type":"array","title":"Modules"}},"type":"object","required":["modules"],"title":"RoleModules"},"RoleUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"edit_system_role":{"type":"boolean","title":"Edit System Role","default":false}},"type":"object","title":"RoleUpdate"},"RoleUpsert":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"modules":{"items":{"type":"string"},"type":"array","title":"Modules","default":[]}},"type":"object","required":["name"],"title":"RoleUpsert"},"RubricaSelectResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Descrição":{"type":"string","title":"Descrição"},"FluxoPositivo":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fluxopositivo"},"CarRelated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Carrelated"}},"type":"object","required":["ID","Descrição"],"title":"RubricaSelectResponse"},"SalaryImportRequest":{"properties":{"movements":{"items":{"$ref":"#/components/schemas/SalaryMovementItem"},"type":"array","title":"Movements"},"payment_method_id":{"type":"integer","title":"Payment Method Id"}},"type":"object","required":["movements","payment_method_id"],"title":"SalaryImportRequest","description":"Bulk salary import request."},"SalaryImportResponse":{"properties":{"inserted_count":{"type":"integer","title":"Inserted Count"},"total_requested":{"type":"integer","title":"Total Requested"},"status":{"type":"string","title":"Status"}},"type":"object","required":["inserted_count","total_requested","status"],"title":"SalaryImportResponse","description":"Response after bulk salary import."},"SalaryMovementItem":{"properties":{"valor_total":{"type":"number","title":"Valor Total","description":"Negative value (expense)"},"colaborador_id":{"type":"integer","title":"Colaborador Id","description":"Cliente.ID matched by IBAN"},"colaborador_nome":{"type":"string","title":"Colaborador Nome","description":"Employee name for display"},"rubrica_id":{"type":"integer","title":"Rubrica Id","description":"Rubrica ID, default 27 for salaries","default":27},"lucro":{"type":"boolean","title":"Lucro","description":"Enters in Lucros e Despesas","default":true},"descricao":{"type":"string","title":"Descricao","description":"'Salário' or 'Subsídio de Alimentação'"},"data_pagamento":{"type":"string","title":"Data Pagamento","description":"Payment date from XML (ISO format)"}},"type":"object","required":["valor_total","colaborador_id","colaborador_nome","descricao","data_pagamento"],"title":"SalaryMovementItem","description":"Single salary movement from SEPA XML."},"SalespersonComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"SalespersonComboItem","description":"Salesperson dropdown item."},"SeatsComboItem":{"properties":{"Id":{"type":"integer","title":"Id"},"Lugares":{"type":"string","title":"Lugares"}},"type":"object","required":["Id","Lugares"],"title":"SeatsComboItem","description":"Seats (lugares) dropdown item."},"SectionComboItem":{"properties":{"id":{"type":"integer","title":"Id"},"section":{"type":"string","title":"Section"},"slug":{"type":"string","title":"Slug"}},"type":"object","required":["id","section","slug"],"title":"SectionComboItem","description":"Integrazu section dropdown item."},"ServiceItem":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","required":["name"],"title":"ServiceItem","description":"A service offered by the company."},"SharesPayload":{"properties":{"recipients":{"items":{"type":"integer"},"type":"array","title":"Recipients","default":[]}},"type":"object","title":"SharesPayload"},"SitemapRequest":{"properties":{"website_id":{"type":"integer","title":"Website Id"}},"type":"object","required":["website_id"],"title":"SitemapRequest"},"StateComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Estado":{"type":"string","title":"Estado"}},"type":"object","required":["ID","Estado"],"title":"StateComboItem","description":"Vehicle state dropdown item."},"StatementSummary":{"properties":{"account_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Ref"},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency"},"date_start":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Start"},"date_end":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date End"},"opening_balance":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,16}|(?=[\\d.]{1,19}0*$)\\d{0,16}\\.\\d{0,2}0*$)"},{"type":"null"}],"title":"Opening Balance"},"closing_balance":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,16}|(?=[\\d.]{1,19}0*$)\\d{0,16}\\.\\d{0,2}0*$)"},{"type":"null"}],"title":"Closing Balance"},"declared_debit_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Declared Debit Count"},"declared_debit_total":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,16}|(?=[\\d.]{1,19}0*$)\\d{0,16}\\.\\d{0,2}0*$)"},{"type":"null"}],"title":"Declared Debit Total"},"declared_credit_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Declared Credit Count"},"declared_credit_total":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,16}|(?=[\\d.]{1,19}0*$)\\d{0,16}\\.\\d{0,2}0*$)"},{"type":"null"}],"title":"Declared Credit Total"}},"type":"object","title":"StatementSummary"},"SupplierComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"SupplierComboItem","description":"Supplier dropdown item."},"SupplierPayResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"ClienteNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Clientenome"},"ValorTotal":{"type":"number","title":"Valortotal"},"MovimentosCount":{"type":"integer","title":"Movimentoscount"}},"type":"object","required":["ID","ClienteNome","ValorTotal","MovimentosCount"],"title":"SupplierPayResponse"},"SupplierSelectResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"},"NIF":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Nif"}},"type":"object","required":["ID","Nome"],"title":"SupplierSelectResponse"},"SuspendContractRequest":{"properties":{"return_vehicle_to_stock":{"type":"boolean","title":"Return Vehicle To Stock","default":false},"vehicle_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vehicle Id"},"vehicle_location":{"anyOf":[{"type":"string","enum":["park","transport"]},{"type":"null"}],"title":"Vehicle Location"},"transport":{"anyOf":[{"$ref":"#/components/schemas/SuspendTransportPayload"},{"type":"null"}]},"suspended_retoma_vehicle_ids":{"items":{"type":"integer"},"type":"array","title":"Suspended Retoma Vehicle Ids"},"side_effects":{"anyOf":[{"$ref":"#/components/schemas/SuspendSideEffects"},{"type":"null"}]}},"type":"object","title":"SuspendContractRequest"},"SuspendSideEffects":{"properties":{"clear_buffer_block_sale":{"type":"boolean","title":"Clear Buffer Block Sale","default":false},"invalidate_listings_cache":{"type":"boolean","title":"Invalidate Listings Cache","default":false},"reset_prep":{"type":"boolean","title":"Reset Prep","default":false},"toggle_pronto_entrega_off":{"type":"boolean","title":"Toggle Pronto Entrega Off","default":false}},"type":"object","title":"SuspendSideEffects","description":"Optional cleanup toggles. All default off; reserved for future UI.\nWired through the workflow so we can enable any of these without an\nAPI change."},"SuspendTransportPayload":{"properties":{"tipo":{"type":"string","enum":["entrada","saida"],"title":"Tipo","default":"entrada"},"origem":{"type":"string","minLength":1,"title":"Origem"},"destino":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Destino"},"destino_park_id":{"type":"integer","title":"Destino Park Id"},"data_recolha":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Recolha"},"data_entrega_prevista":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Entrega Prevista"},"notas":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notas"}},"type":"object","required":["origem","destino_park_id"],"title":"SuspendTransportPayload","description":"Mirrors the body of POST /vehicles/{id}/transportes."},"SyncJobStatus":{"properties":{"job_id":{"type":"string","title":"Job Id"},"vehicle_id":{"type":"integer","title":"Vehicle Id"},"status":{"type":"string","title":"Status"},"current_step":{"type":"string","title":"Current Step"},"progress":{"type":"integer","title":"Progress"},"adverts_found":{"type":"integer","title":"Adverts Found"},"adverts_synced":{"type":"integer","title":"Adverts Synced"},"adverts_failed":{"type":"integer","title":"Adverts Failed"},"steps":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Steps"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["job_id","vehicle_id","status","current_step","progress","adverts_found","adverts_synced","adverts_failed","steps","created_at","completed_at","error"],"title":"SyncJobStatus","description":"Response model for sync job status."},"TaskCreate":{"properties":{"subject":{"type":"string","maxLength":255,"minLength":1,"title":"Subject"},"description":{"type":"string","maxLength":500,"minLength":1,"title":"Description"},"execution_date":{"type":"string","title":"Execution Date"},"task_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Type"}},"type":"object","required":["subject","description","execution_date"],"title":"TaskCreate"},"TaskDTO":{"properties":{"id":{"type":"integer","title":"Id"},"lead_id":{"type":"integer","title":"Lead Id"},"subject":{"type":"string","title":"Subject"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"execution_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Execution Date"},"completed":{"type":"boolean","title":"Completed","default":false},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","lead_id","subject","description","execution_date"],"title":"TaskDTO"},"TaskUpdate":{"properties":{"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"execution_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Execution Date"},"completed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Completed"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["subject","description","execution_date"],"title":"TaskUpdate"},"TicketUpdate":{"properties":{"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"priority":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Priority"},"assigned_to":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Assigned To"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"internal_priority":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Internal Priority"},"hold_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hold Reason"}},"type":"object","title":"TicketUpdate"},"TipoCasaComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"TipoCasaComboItem","description":"Tipo casa dropdown item."},"TipoClienteComboItem":{"properties":{"ID":{"type":"integer","title":"Id"},"Nome":{"type":"string","title":"Nome"}},"type":"object","required":["ID","Nome"],"title":"TipoClienteComboItem","description":"Tipo cliente dropdown item."},"TrackEventRequest":{"properties":{"visitor_id":{"type":"string","title":"Visitor Id","description":"Unique visitor identifier (UUID)"},"event_type":{"type":"string","title":"Event Type","description":"Event type: page_view, form_submit, click, scroll, engagement"},"page_url":{"type":"string","title":"Page Url","description":"Current page URL"},"page_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page Title","description":"Page title"},"event_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Name","description":"Specific event name"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Additional event data"},"utm":{"anyOf":[{"$ref":"#/components/schemas/UTMParams"},{"type":"null"}],"description":"UTM parameters"}},"type":"object","required":["visitor_id","event_type","page_url"],"title":"TrackEventRequest"},"TrustSignals":{"properties":{"certifications":{"items":{"type":"string"},"type":"array","title":"Certifications","default":[]},"years_in_business":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Years In Business"},"awards":{"items":{"type":"string"},"type":"array","title":"Awards","default":[]},"team_size":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Size"},"partnerships":{"items":{"type":"string"},"type":"array","title":"Partnerships","default":[]}},"type":"object","title":"TrustSignals","description":"Trust signals and credentials."},"UTMParams":{"properties":{"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Source"},"utm_medium":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Medium"},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Campaign"},"utm_term":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Term"},"utm_content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Content"}},"type":"object","title":"UTMParams"},"UpdateWarningCreate":{"properties":{"message":{"type":"string","maxLength":1000,"minLength":1,"title":"Message"},"ttl_minutes":{"type":"integer","title":"Ttl Minutes","default":15},"severity":{"type":"string","title":"Severity","default":"warning"}},"type":"object","required":["message"],"title":"UpdateWarningCreate"},"UserRolesAssign":{"properties":{"idrole_ids":{"items":{"type":"integer"},"type":"array","title":"Idrole Ids"}},"type":"object","required":["idrole_ids"],"title":"UserRolesAssign"},"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"},"VehicleBlockResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula"},"MatriculaSecundaria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matriculasecundaria"},"Marca":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marca"},"Modelo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Modelo"},"Segmento":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Segmento"},"Quadro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quadro","description":"Chassis number"},"Km":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Km"},"Caixa":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caixa","description":"Gearbox"},"Combust":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Combust","description":"Fuel type"},"Cor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cor","description":"Color"},"Preco":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Preco","description":"Price"},"Datamat":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datamat","description":"Registration date"},"Motor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motor"},"RegimeIVA":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Regimeiva","description":"VAT regime"},"Cilindrada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cilindrada","description":"Engine displacement"},"Lugares":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lugares","description":"Number of seats"},"Potencia":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Potencia","description":"Power"},"Peso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Peso","description":"Weight"},"Portas":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Portas","description":"Number of doors"},"Versao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Versao","description":"Version"},"Fornece":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fornece","description":"Supplier name"},"bucketurl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bucketurl","description":"Vehicle photo URL"}},"type":"object","required":["ID","Matricula","MatriculaSecundaria","Marca","Modelo","Segmento","Km","Motor"],"title":"VehicleBlockResponse","description":"Vehicle data for contract block."},"VehicleContractResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Viatura":{"type":"integer","title":"Viatura"},"Cliente":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cliente"},"Nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"ClienteNIF":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Clientenif"},"ClienteContacto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Clientecontacto"},"Data":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data"},"Dataentrega":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataentrega"},"Datafecho":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafecho"},"Reservaate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Reservaate"},"ValorReserva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valorreserva"},"ValorVenda":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valorvenda"},"ValoremFalta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valoremfalta"},"Iva":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Iva"},"IDestado":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idestado"},"EstadoNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Estadonome"},"Fechado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fechado"},"financiado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Financiado"},"temretoma":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Temretoma"},"garantia":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Garantia"},"meses_garantia":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Meses Garantia"},"Oferta1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta1"},"Oferta2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta2"},"Oferta3":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta3"},"Oferta4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta4"},"Oferta5":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta5"},"Oferta6":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oferta6"},"transportepara":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transportepara"},"Comercial":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Comercial"},"ComercialNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comercialnome"},"idresponsavel":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idresponsavel"},"ResponsavelNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Responsavelnome"},"FaturaID":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Faturaid"},"IDpontodevenda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idpontodevenda"},"PontoDeVendaNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pontodevendanome"},"bucketurl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bucketurl"},"ViaturaMatricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Viaturamatricula"},"ViaturaMarca":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Viaturamarca"},"ViaturaModelo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Viaturamodelo"}},"type":"object","required":["ID","Viatura"],"title":"VehicleContractResponse","description":"Vehicle contract response with full contract details."},"VehicleCreate":{"properties":{"Matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula","description":"Primary license plate"},"MatriculaSecundaria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matriculasecundaria","description":"Secondary license plate (national)"},"code_matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Matricula","description":"Primary license plate country code"},"code_matricula_secundaria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Matricula Secundaria","description":"Secondary license plate country code"},"Quadro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quadro","description":"VIN/Chassis number"},"Marca":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Marca","description":"Brand ID (FK to MarcasViatura)"},"Modelo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Modelo","description":"Model ID (FK to ModelosViatura)"},"Versao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Versao","description":"Version/Trim"},"Km":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Km","description":"Mileage in kilometers"},"Motor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motor","description":"Engine code"},"Cilindrada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cilindrada","description":"Engine displacement (cc)"},"Potencia":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Potencia","description":"Power (HP or kW)"},"Combust":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Combust","description":"Fuel type ID (FK to CombustivelViatura)"},"Caixa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Caixa","description":"Gearbox ID (FK to CaixaVelocidadesViatura)"},"Cor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cor","description":"Color ID (FK to CoresViatura)"},"Lugares":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lugares","description":"Number of seats (FK to LugaresViatura)"},"Portas":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Portas","description":"Number of doors (FK to PortasViatura)"},"Peso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Peso","description":"Weight in kg"},"Segmento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Segmento","description":"Segment/Type ID (FK to TipoViatura)"},"Subsegmento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Subsegmento","description":"Subsegment ID (FK to Subsegmentos)"},"Estado":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estado","description":"State ID (1=new, 2=sold, 3=reserved, 4=to close)"},"Preço":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Preço","description":"Sale price"},"ValorSelo":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valorselo","description":"Stamp tax value"},"RegimeIva":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Regimeiva","description":"VAT regime ID (FK to RegimeIva)"},"Dataentr":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataentr","description":"Entry date"},"Datamat":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datamat","description":"First registration date"},"Data_Imp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data Imp","description":"Import date"},"data_mat_nacional":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data Mat Nacional","description":"National registration date"},"ValInsp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valinsp","description":"Inspection validity date"},"Fornece":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornece","description":"Supplier ID (FK to Cliente)"},"Ponto_de_venda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ponto De Venda","description":"Point of sale ID (FK to PontosDeVenda)"},"IDempresa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idempresa","description":"Company ID - auto-set from authenticated user"},"current_park_location_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Park Location Id","description":"Current physical park location (FK to Z_ParkLocations). Required when the vehicle is created with localizacao=0 (em parque). Validated at route layer to belong to the same company."},"Consignado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Consignado","description":"Consigned vehicle","default":false},"Emprestado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Emprestado","description":"Loaned vehicle","default":false},"Seguro":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Seguro","description":"Insured","default":false},"Importado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Importado","description":"Imported","default":false},"stockpartilhado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Stockpartilhado","description":"Shared stock","default":false},"hidden":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Hidden","description":"Hidden from listings","default":false},"fechado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fechado","description":"Closed","default":false},"datafecho":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafecho","description":"Close date"},"Fotos":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fotos","description":"Photos JSON or CSV"},"bucketurl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bucketurl","description":"S3 bucket URL for main photo"},"Observacoes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Observacoes","description":"Observations/Notes"},"IDeasydata":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ideasydata","description":"EasyData ID"},"Estadoeasydata":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estadoeasydata","description":"EasyData state"},"reference":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reference","description":"External reference"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id","description":"Integrazu version ID"},"gearbox_type_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Type Id","description":"Integrazu gearbox type ID"},"gearbox_shift_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Shift Id","description":"Integrazu gearbox shift ID"},"section_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Section Id","description":"Integrazu section ID"},"second_key_status":{"anyOf":[{"type":"string","enum":["sim","não","requisitado"]},{"type":"null"}],"title":"Second Key Status","description":"Second-key status"}},"type":"object","title":"VehicleCreate","description":"Create new vehicle request."},"VehicleOcrResult":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"billed":{"type":"boolean","title":"Billed","default":false},"doc_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doc Type"},"confianca":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confianca"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","default":[]},"matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula"},"vin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vin"},"marca_texto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marca Texto"},"modelo_texto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Modelo Texto"},"versao_texto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Versao Texto"},"data_primeira_matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Primeira Matricula"},"data_matricula_nacional":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Matricula Nacional"},"cilindrada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cilindrada"},"combustivel_texto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Combustivel Texto"},"potencia_cv":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Potencia Cv"},"cor_texto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cor Texto"},"caixa_texto":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caixa Texto"},"lugares":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lugares"},"portas":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Portas"},"peso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Peso"},"categoria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Categoria"}},"type":"object","title":"VehicleOcrResult","description":"Result of POST /api/vehicles/ocr-document (QRProcessResult-style contract:\nflat raw-text fields + success/error_message — an unreadable document is\nsuccess=False, never a 500).\n\nText fields (marca_texto, combustivel_texto, cor_texto, ...) are the literal\nstrings printed on the document — id resolution happens in the FE, inside the\nsection-scoped Integrazu cascade (see docs/claude/rules/vehicle-id-spaces.md)."},"VehicleResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula"},"MatriculaSecundaria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matriculasecundaria"},"code_matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Matricula"},"code_matricula_secundaria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Matricula Secundaria"},"Quadro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quadro"},"Marca":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Marca"},"Modelo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Modelo"},"Versao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Versao"},"Tipo":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Tipo"},"Km":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Km"},"Motor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motor"},"Cilindrada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cilindrada"},"Potencia":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Potencia"},"Combust":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Combust"},"Caixa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Caixa"},"Cor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cor"},"Lugares":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lugares"},"Portas":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Portas"},"Peso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Peso"},"Segmento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Segmento"},"Subsegmento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Subsegmento"},"Estado":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estado"},"Preço":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Preço"},"ValorSelo":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valorselo"},"PreçoPintura":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Preçopintura"},"RegimeIva":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Regimeiva"},"Dataentr":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataentr"},"Datamat":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datamat"},"Data_Imp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data Imp"},"data_mat_nacional":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data Mat Nacional"},"ValInsp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valinsp"},"datafecho":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafecho"},"Fornece":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornece"},"Ponto_de_Venda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ponto De Venda"},"IDempresa":{"type":"integer","title":"Idempresa"},"current_park_location_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Park Location Id"},"fechado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fechado","default":false},"consignado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Consignado","default":false},"Emprestado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Emprestado","default":false},"Seguro":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Seguro","default":false},"Importado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Importado","default":false},"stockpartilhado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Stockpartilhado","default":false},"hidden":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Hidden","default":false},"Fotos":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fotos"},"bucketurl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bucketurl"},"Observacoes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Observacoes"},"IDeasydata":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ideasydata"},"Estadoeasydata":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estadoeasydata"},"reference":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reference"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id"},"gearbox_type_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Type Id"},"gearbox_shift_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Shift Id"},"section_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Section Id"},"second_key_status":{"anyOf":[{"type":"string","enum":["sim","não","requisitado"]},{"type":"null"}],"title":"Second Key Status"}},"type":"object","required":["ID","IDempresa"],"title":"VehicleResponse","description":"Complete vehicle response - matches Viatura table columns.\nAll fields return IDs (hydrated) - use combo endpoints to get labels."},"VehicleSearchResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"Matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula"},"MatriculaSecundaria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matriculasecundaria"},"Quadro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quadro"},"Marca":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Marca"},"MarcaNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marcanome"},"Modelo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Modelo"},"ModeloNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Modelonome"},"Cor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cor"},"CorNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cornome"},"Estado":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estado"},"EstadoNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Estadonome"},"Caixa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Caixa"},"CaixaNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caixanome"},"Ponto_de_Venda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ponto De Venda"},"PontoDeVendaNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pontodevendanome"},"Km":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Km"},"Preço":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Preço"},"bucketurl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bucketurl"},"Observacoes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Observacoes"}},"type":"object","required":["ID"],"title":"VehicleSearchResponse","description":"Vehicle search response - hydrated with IDs + names for display."},"VehicleSelectResponse":{"properties":{"ID":{"type":"integer","title":"Id"},"DisplayName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Displayname"},"MarcaNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marcanome"},"ModeloNome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Modelonome"},"Quadro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quadro"},"Matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula"},"MatriculaSecundaria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matriculasecundaria"}},"type":"object","required":["ID","DisplayName"],"title":"VehicleSelectResponse"},"VehicleUpdate":{"properties":{"Matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula"},"MatriculaSecundaria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matriculasecundaria"},"code_matricula":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Matricula"},"code_matricula_secundaria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Matricula Secundaria"},"Quadro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quadro"},"Marca":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Marca"},"Modelo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Modelo"},"Versao":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Versao"},"Km":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Km"},"Motor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motor"},"Cilindrada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cilindrada"},"Potencia":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Potencia"},"Combust":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Combust"},"Caixa":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Caixa"},"Cor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cor"},"Lugares":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lugares"},"Portas":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Portas"},"Peso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Peso"},"Segmento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Segmento"},"Subsegmento":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Subsegmento"},"Estado":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estado"},"Preço":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Preço"},"ValorSelo":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valorselo"},"RegimeIva":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Regimeiva"},"Dataentr":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Dataentr"},"Datamat":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datamat"},"Data_Imp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data Imp"},"data_mat_nacional":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Data Mat Nacional"},"ValInsp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valinsp"},"Fornece":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fornece"},"Ponto_de_venda":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ponto De Venda"},"current_park_location_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Park Location Id"},"Consignado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Consignado"},"Emprestado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Emprestado"},"Seguro":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Seguro"},"Importado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Importado"},"stockpartilhado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Stockpartilhado"},"hidden":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Hidden"},"fechado":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fechado"},"datafecho":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Datafecho"},"Fotos":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fotos"},"bucketurl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bucketurl"},"Observacoes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Observacoes"},"IDeasydata":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ideasydata"},"Estadoeasydata":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estadoeasydata"},"reference":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reference"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id"},"gearbox_type_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Type Id"},"gearbox_shift_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Gearbox Shift Id"},"section_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Section Id"},"second_key_status":{"anyOf":[{"type":"string","enum":["sim","não","requisitado"]},{"type":"null"}],"title":"Second Key Status"}},"type":"object","title":"VehicleUpdate","description":"Update vehicle request (all fields optional)."},"VersionComboItem":{"properties":{"id":{"type":"integer","title":"Id"},"version":{"type":"string","title":"Version"}},"type":"object","required":["id","version"],"title":"VersionComboItem","description":"Integrazu version dropdown item."},"ViesLookupResponse":{"properties":{"available":{"type":"boolean","title":"Available"},"found":{"type":"boolean","title":"Found","default":false},"valid":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Valid"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"morada":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Morada"},"codigo_postal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codigo Postal"},"localidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localidade"},"cidade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cidade"},"pais":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pais"}},"type":"object","required":["available"],"title":"ViesLookupResponse","description":"VIES registry lookup result.\n\n`available=False` means the lookup could not run (VIES outage, or the NIF\nhas no derivable member state) — distinct from a definitive miss."},"VoteRequest":{"properties":{"vote":{"type":"string","enum":["APPROVED","REJECTED"],"title":"Vote"}},"type":"object","required":["vote"],"title":"VoteRequest","description":"Body for POST /api/socios/change-requests/{id}/vote."},"WarrantyComboItem":{"properties":{"id":{"type":"integer","title":"Id"},"warranty_name":{"type":"string","title":"Warranty Name"},"template_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Template Id"}},"type":"object","required":["id","warranty_name"],"title":"WarrantyComboItem","description":"Warranty dropdown item from Z_Warranties."},"WizardPVCreate":{"properties":{"DESIGANCAO":{"type":"string","maxLength":255,"minLength":1,"title":"Desigancao"},"NomeComercial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nomecomercial"},"Nome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nome"},"EMAIL":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},"type":"object","required":["DESIGANCAO"],"title":"WizardPVCreate","description":"Lightweight PV creation model for onboarding wizard."},"_BrandEnrichedImagesIn":{"properties":{"brand_id":{"type":"integer","title":"Brand Id"},"enriched_images":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enriched Images"}},"type":"object","required":["brand_id"],"title":"_BrandEnrichedImagesIn"},"_EnrichedImagesIn":{"properties":{"enriched_images":{"type":"boolean","title":"Enriched Images"}},"type":"object","required":["enriched_images"],"title":"_EnrichedImagesIn"},"app__models__documents__SendEmailResult":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"},"recipient":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipient"}},"type":"object","required":["success","message"],"title":"SendEmailResult","description":"Result of sending document via email."},"app__models__invoices__SendEmailResult":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"},"recipient":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipient"}},"type":"object","required":["success","message"],"title":"SendEmailResult","description":"Result of sending email."},"app__routes__ai_generator__JobStatusResponse":{"properties":{"job_id":{"type":"integer","title":"Job Id"},"website_id":{"type":"integer","title":"Website Id"},"target_domain":{"type":"string","title":"Target Domain"},"status":{"type":"string","title":"Status"},"progress":{"type":"integer","title":"Progress"},"current_step":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Step"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"},"is_stale":{"type":"boolean","title":"Is Stale","default":false}},"type":"object","required":["job_id","website_id","target_domain","status","progress","current_step","result","error_message","created_at","updated_at","completed_at"],"title":"JobStatusResponse"},"app__routes__ai_page_generator__JobStatusResponse":{"properties":{"job_id":{"type":"integer","title":"Job Id"},"website_id":{"type":"integer","title":"Website Id"},"target_domain":{"type":"string","title":"Target Domain"},"status":{"type":"string","title":"Status"},"progress":{"type":"integer","title":"Progress"},"current_step":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Step"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["job_id","website_id","target_domain","status","progress","current_step","result","error_message","created_at","updated_at","completed_at"],"title":"JobStatusResponse"}},"securitySchemes":{"APIToken":{"type":"apiKey","in":"header","name":"x-api-token","description":"Company API token (from Settings > API Tokens)."},"OriginVerify":{"type":"apiKey","in":"header","name":"x-origin-verify","description":"Origin verification header (nginx bypass)."}}},"security":[{"APIToken":[],"OriginVerify":[]}]}