{"openapi":"3.1.0","info":{"title":"Vezzo API","version":"1.0.0","description":"API pública do Vezzo (fila virtual). Autenticação OAuth 2.0 com **client credentials**.\n\n1. Crie o cliente em **admin.vezzo.io → API e integrações** e guarde o `client_id` e o `client_secret` (o segredo aparece uma vez só).\n2. Peça o token: `POST https://api.vezzo.io/api/oauth/token` com `grant_type=client_credentials` e as credenciais em `Authorization: Basic base64(client_id:client_secret)`.\n3. Use `Authorization: Bearer <access_token>` nas rotas abaixo. O token vale 60 minutos; peça outro quando vencer.\n\nRespostas de sucesso vêm em `{ \"data\": ... }`; erros em `{ \"error\": { \"code\", \"message\", \"field\" } }`. Limite: 120 chamadas por minuto por cliente.\n\nClientes de **estabelecimento** acessam só o próprio estabelecimento. Clientes da **plataforma** só leem dados gerais.","contact":{"name":"Vezzo","email":"contato@vezzo.io"}},"servers":[{"url":"https://api.vezzo.io"}],"tags":[{"name":"Autenticação"},{"name":"Fila","description":"Cliente de estabelecimento"},{"name":"Relatórios","description":"Cliente de estabelecimento"},{"name":"Plataforma","description":"Cliente da plataforma"}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.vezzo.io/api/oauth/token","scopes":{"queue:read":"Ler a fila ao vivo","queue:write":"Colocar pessoas na fila, chamar e encerrar senhas, abrir e pausar a fila","metrics:read":"Ler métricas do estabelecimento","customers:read":"Ler a lista de clientes (nome e celular)","platform:read":"Ler estabelecimentos e números da plataforma"}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"INSUFFICIENT_SCOPE"},"message":{"type":"string"},"field":{"type":"string"}}}}},"Token":{"type":"object","properties":{"access_token":{"type":"string","example":"vzt_…"},"token_type":{"type":"string","example":"Bearer"},"expires_in":{"type":"integer","example":3600},"scope":{"type":"string","example":"queue:read queue:write"}}},"Ticket":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string","example":"A-012"},"name":{"type":"string","description":"Primeiro nome"},"partySize":{"type":"integer"},"status":{"type":"string","enum":["waiting","called","served","no_show","canceled","removed"]}}},"Queue":{"type":"object","description":"Estado da fila: estabelecimento, chamados, aguardando e números do dia","properties":{"venue":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"queueState":{"type":"string","enum":["open","paused","closed"]}}},"called":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}},"waiting":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}},"metrics":{"type":"object","additionalProperties":true}}}}},"paths":{"/api/oauth/token":{"post":{"tags":["Autenticação"],"summary":"Pedir um token de acesso (client credentials)","security":[],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["grant_type"],"properties":{"grant_type":{"type":"string","enum":["client_credentials"]},"scope":{"type":"string","description":"Opcional: só parte das permissões, separadas por espaço"},"client_id":{"type":"string","description":"Se não usar o cabeçalho Basic"},"client_secret":{"type":"string","description":"Se não usar o cabeçalho Basic"}}}}}},"responses":{"200":{"description":"Token emitido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"400":{"description":"invalid_request / unsupported_grant_type / invalid_scope"},"401":{"description":"invalid_client"}}}},"/api/v1/me":{"get":{"tags":["Autenticação"],"summary":"Quem é este token","security":[{"oauth2":["queue:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/queue":{"get":{"tags":["Fila"],"summary":"Fila ao vivo","security":[{"oauth2":["queue:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Queue"}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/queue/tickets":{"post":{"tags":["Fila"],"summary":"Colocar uma pessoa na fila","security":[{"oauth2":["queue:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":60},"party_size":{"type":"integer","minimum":1,"maximum":30,"default":1}}}}}},"responses":{"201":{"description":"Senha criada","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"ticket":{"type":"object","properties":{"label":{"type":"string"},"token":{"type":"string"}}},"queue":{"$ref":"#/components/schemas/Queue"}}}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/queue/call-next":{"post":{"tags":["Fila"],"summary":"Chamar a próxima senha","security":[{"oauth2":["queue:write"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"called":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"}}},"queue":{"$ref":"#/components/schemas/Queue"}}}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Ninguém aguardando","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/queue/state":{"patch":{"tags":["Fila"],"summary":"Abrir, pausar ou fechar a fila","security":[{"oauth2":["queue:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state"],"properties":{"state":{"type":"string","enum":["open","paused","closed"]},"reason":{"type":"string","maxLength":120}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Queue"}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tickets/{id}/{action}":{"post":{"tags":["Fila"],"summary":"Ação numa senha","security":[{"oauth2":["queue:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"action","in":"path","required":true,"schema":{"type":"string","enum":["call","recall","serve","no-show","remove","requeue"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Queue"}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A ação não vale para a situação atual da senha","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/metrics":{"get":{"tags":["Relatórios"],"summary":"Métricas do período","security":[{"oauth2":["metrics:read"]}],"parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30}},{"name":"from","in":"query","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/customers":{"get":{"tags":["Relatórios"],"summary":"Clientes do período (nome e celular)","description":"Dado pessoal (LGPD): cada leitura fica registrada no histórico do Vezzo.","security":[{"oauth2":["customers:read"]}],"parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30}},{"name":"from","in":"query","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","schema":{"type":"string","format":"date"}},{"name":"view","in":"query","schema":{"type":"string","enum":["clientes","visitas"]}},{"name":"q","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/admin/venues":{"get":{"tags":["Plataforma"],"summary":"Estabelecimentos","security":[{"oauth2":["platform:read"]}],"parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"plan","in":"query","schema":{"type":"string","enum":["basic","premium","global"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/admin/overview":{"get":{"tags":["Plataforma"],"summary":"Números da plataforma agora","security":[{"oauth2":["platform:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"401":{"description":"Token ausente, inválido ou vencido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Token sem a permissão (escopo) necessária","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Limite de 120 chamadas por minuto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}