Desenvolvedores
A API da Meevia
Leia a agenda, marque agendamentos e consulte o catálogo e a ficha do paciente a partir do seu próprio sistema. Esta página leva você da primeira chave à primeira resposta com sucesso.
Nesta página
O que é e para quem serve
A API abre, para o seu sistema, as partes da clínica que fazem sentido automatizar: a agenda, o catálogo de profissionais e procedimentos, e a ficha básica do paciente. O que você faz por ela segue as mesmas regras que valem para quem opera a clínica dentro da plataforma.
É HTTP com JSON, sem biblioteca obrigatória e sem SDK para instalar. Se o seu ambiente sabe fazer uma requisição e ler uma resposta, ele já sabe conversar com a Meevia.
Casos comuns
- Um site ou aplicativo próprio onde o paciente escolhe o horário e marca sozinho.
- Um sistema que a clínica já usa e que precisa enxergar a agenda do dia sem ninguém digitar duas vezes.
- Automação interna: um painel próprio, um relatório, uma rotina que confirma presença.
O que a clínica precisa ter
O acesso à API faz parte do plano da clínica. Se o plano atual não tiver esse acesso, a primeira chamada já volta recusada, e isso nenhuma mudança no seu código resolve: é conversa com o time comercial.
O que ainda não está aqui
Esta versão lê e escreve agenda, e lê catálogo e paciente. A Meevia avisar o seu sistema quando algo acontece na clínica, cobrança e pagamento não fazem parte dela.
Como obter uma chave
A chave nasce no painel de desenvolvedor, que fica em developers.meevia.app e tem casca própria, fora do sistema da clínica. É assim porque quem integra muitas vezes não é da clínica. Não existe caminho pela API para criar uma chave.
Abrir o painel de desenvolvedor
- 1Abra o painel de desenvolvedorO endereço é developers.meevia.app. Quem já trabalha dentro do sistema da clínica chega pelo mesmo lugar por Integrações, no card de API e Webhooks, que é uma porta para o painel.
- 2Entre com a sua conta, ou peça um conviteQuem administra a clínica entra direto. Quem é de fora precisa ser convidado: na aba Acessos, quem administra o painel convida pelo e-mail e escolhe entre Somente ver, que consulta, e Pode administrar, que também emite chave. Pedir o convite é melhor que pedir a chave pronta, porque chave que viaja por mensagem já vazou.
- 3Escolha a clínicaO painel atende todas as clínicas em que você tem acesso, e a escolhida no alto é a dona de tudo que as abas mostram. Trabalhando para várias, é aqui que você troca.
- 4Na aba Chaves, crie uma chave novaDê um nome que diga onde ela vai ser usada. Seis meses depois, esse nome é a única forma de revogar a chave certa sem derrubar a integração errada.
- 5Escolha o modo e os escoposO modo decide se a chave mexe na clínica de verdade ou no ambiente de teste. Os escopos decidem o que ela pode fazer. Marque só o que a integração precisa.
- 6Copie a chave antes de fechar a janelaA chave completa aparece uma única vez, na emissão. A Meevia guarda o pedaço que a identifica e nunca a parte secreta, então fechar sem copiar não tem recuperação: revogue a chave e emita outra.
Uma chave, uma clínica
A chave vale para a clínica que a emitiu, e só para ela. Se você atende várias clínicas, são várias chaves, cada uma guardada separada e trocável sem mexer nas outras. Não existe chave que enxergue mais de uma clínica.
Onde guardar
Guarde a chave no servidor, no cofre de variáveis do seu ambiente. Chave dentro do código de um aplicativo ou de uma página é chave publicada, porque qualquer pessoa consegue ler.
Quando revogar
Revogar vale na hora e não tem volta: a chave para de funcionar e as chamadas dela passam a ser recusadas. Faça isso ao trocar de fornecedor, ao desligar uma integração e na menor suspeita de vazamento.
Quem pode o quê
O papel Pode administrar no painel abre as duas coisas que mexem: emitir e revogar chave, e reiniciar o ambiente de teste. Ele se recebe por convite e vale por clínica, então quem vem de fora faz as duas sem depender de ninguém. Reiniciar tem um segundo caminho: quem administra a clínica também reinicia. Quem só tem Somente ver enxerga as chaves e não emite nenhuma; o painel avisa isso na tela, em vez de esconder o botão.
Autenticação
Toda chamada vai autenticada. A chave viaja no cabeçalho de autorização, no esquema que o exemplo mostra, e é só isso: não há login, sessão nem token que vence no meio do caminho.
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/practitioners"A chave é um valor único. É ele inteiro que viaja no cabeçalho. Ela tem três pedaços colados: o prefixo diz em que modo a chave está, o pedaço do meio a identifica e é o que aparece na aba Chaves do painel, e o último é a parte secreta. Essa última a Meevia nunca guarda em claro, então nem o suporte consegue ler a sua. Envie sempre a chave completa: mandar só a parte secreta é o engano que mais rende recusa de autorização.
Chave ausente, escrita errada, revogada ou vencida recebem todas a mesma recusa, sem dizer qual dos quatro casos foi. É de propósito. Dizer qual é dar pista a quem está tentando adivinhar.
Dois modos
Produção
mv_live_
Mexe na clínica de verdade. Um agendamento criado por aqui aparece na agenda da recepção e dispara o que a clínica configurou disparar.
Teste
mv_test_
Mexe num ambiente separado, com dados de mentira, que existe só para você experimentar. Nada do que acontece ali encosta na clínica real.
O modo é decidido na emissão e não muda depois. Na prática você mantém as duas chaves e troca a variável de ambiente para virar de um lado para o outro.
A chave que aparece nos exemplos é inventada e não funciona em lugar nenhum: ela está ali só para você reconhecer o formato da sua. Repare que o prefixo dela é de produção. Fazendo o passo a passo no modo de teste, como esta página recomenda, a sua vai começar diferente.
Escopos
Cada escopo abre uma parte da API, e a chave só faz o que os escopos dela permitem. A falta de um escopo aparece na primeira chamada que precisa dele, não na emissão.
appointments:read
Ler a agenda
Listar os agendamentos de um período e abrir um deles.
appointments:write
Mexer na agenda
Criar agendamento, mudar a situação de um e cancelar.
catalog:read
Ler o catálogo
Profissionais, procedimentos e os horários livres de um dia.
patients:read
Ler paciente
Abrir a ficha básica de um paciente que você já conhece pelo identificador. Não existe busca aberta por nome nesta versão.
Conceda o mínimo. Uma integração que só mostra a agenda num telão não precisa poder marcar agendamento. E uma chave enxuta é um estrago pequeno no dia em que ela vazar.
Escopo não se edita depois da emissão. Ampliar é emitir uma chave nova com o que falta, trocar no seu ambiente e revogar a antiga.
Ambiente de teste
A clínica ganha um ambiente de teste só dela, isolado da clínica real. A primeira chave de teste emitida já cria esse ambiente, então não há nada a provisionar nem a pedir.
O que já vem dentro
Vem um paciente, um procedimento e um profissional de exemplo. Nenhum deles existe na clínica de verdade. As listas de profissionais e de procedimentos devolvem os identificadores desses dois, então consultar catálogo e horário livre funciona na primeira sessão. Cadastro é da clínica: pela API, o que se cria é agendamento.
O que não dá para testar aqui
A API escreve em três lugares: criar agendamento, mudar a situação de um e cancelar. Hoje nenhum dos três dá para exercitar aqui, e o motivo vem em cadeia. Criar precisa do identificador do paciente, que não aparece na tela nem volta de nenhuma consulta, porque não há listagem de pacientes. Mudar a situação e cancelar precisam do identificador de um agendamento, e ele só existiria se criar tivesse funcionado: a lista de agendamentos nasce vazia aqui. Quem precisa testar escrita faz isso na clínica de verdade, com o cuidado que isso pede: marque num horário vazio e cancele assim que confirmar que funcionou.
Como reiniciar
A aba Ambiente de teste, no painel, tem um botão que descarta o ambiente atual e entrega outro, limpo, com os mesmos dados iniciais. As chaves de teste já emitidas continuam valendo: elas estão ligadas à clínica, não ao ambiente que foi descartado.
Reiniciar apaga tudo que você criou ali, e não há desfazer. É o que você quer quando um teste sujou o ambiente, e é o que você não quer no meio de uma bateria de testes.
Reiniciar é de quem tem Pode administrar no painel ou administra a clínica. Quem vem de fora com esse papel reinicia sozinho, sem ter a quem pedir.
O endereço da API
Toda chamada sai para o mesmo endereço, e ele é um só para todo mundo. Não existe um endereço por clínica: quem separa uma clínica da outra é a chave, nunca a URL.
https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1Repare que há um pedaço que parece repetido no meio do caminho. Está certo assim. Um deles é da infraestrutura que hospeda a API e o outro é da versão da nossa. Copie o endereço exatamente como aparece aqui; tirar a parte que parece sobrando devolve uma resposta de endereço inexistente.
Primeira chamada, do zero à primeira resposta
Leva cinco minutos, contando do login. Faça no modo de teste: se algo sair diferente do esperado, quem paga é um paciente de mentira.
- 1Emita uma chave de testeSiga o caminho descrito em Como obter uma chave, marcando o modo de teste e o escopo de leitura do catálogo. Copie a chave.
- 2Guarde a chave numa variável de ambienteAssim a chave não fica no histórico do terminal nem colada no meio do comando que você vai mandar para um colega.
- 3Peça a lista de profissionaisÉ a chamada mais simples daqui: não recebe parâmetro nenhum, e o ambiente de teste já vem com um profissional dentro. Se ela responder, sua chave, seu escopo e seu endereço estão certos de uma vez só.
- 4Confira o que voltouUma resposta bem-sucedida traz o profissional de teste. Daí em diante a receita é a mesma para o resto: muda o endereço, o cabeçalho continua igual.
Troque a chave de exemplo pela variável em que você guardou a sua no passo anterior, ou pela chave inteira. A que aparece aqui é inventada, e volta recusada.
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/practitioners"{
"data": [
{
"id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"name": "Dra. Helena Costa",
"specialty": "Dermatologia"
}
]
}Se não veio o que você esperava
Compare o que voltou com o catálogo de recusas desta página, que diz o que aconteceu e o que fazer em cada caso. Vale olhar também a aba Requisições do painel, que mostra o endereço chamado, a resposta e o horário de cada chamada recebida. Ela guarda só esse resumo, nunca o conteúdo enviado.
O formato das respostas
As respostas vêm embrulhadas sempre do mesmo jeito, e cada chamada mostra o formato do que ela devolve. Programe contra o embrulho e ignore o que não conhece: com o tempo aparecem informações novas, e a integração que ignora o que não espera sobrevive a isso sem precisar de você.
Os embrulhos
- Um registro só, dentro do embrulho padrão.
data - Uma lista, dentro do mesmo embrulho.
data - Uma lista em páginas, acompanhada do marcador que pede a próxima.
datanext_cursorPode vir sem valor - Esta resposta foge do padrão das outras: ela traz o dia consultado ao lado dos horários.
dateslots - O formato de toda recusa, em qualquer chamada.
error
Listas longas
Listas vêm em páginas. A resposta traz um marcador de continuação: enquanto ele vier preenchido, mande esse mesmo marcador na chamada seguinte para pegar a próxima página. Quando vier sem valor, acabou. Não tente adivinhar o total nem montar a paginação por conta própria.
O que cada resposta carrega
Agendamento
| Campo | Tipo |
|---|---|
id | uuid |
status | string |
starts_at | datetime |
ends_atPode vir sem valor | datetime |
patient_idPode vir sem valor | uuid |
professional_idPode vir sem valor | uuid |
procedure_ids | array<uuid> |
created_at | datetime |
Paciente
| Campo | Tipo |
|---|---|
id | uuid |
name | string |
phonePode vir sem valor | string |
emailPode vir sem valor | string |
Profissional
| Campo | Tipo |
|---|---|
id | uuid |
namePode vir sem valor | string |
specialtyPode vir sem valor | string |
Procedimento
| Campo | Tipo |
|---|---|
id | uuid |
name | string |
price | number |
duration_minutes | integer |
Horário livre
| Campo | Tipo |
|---|---|
time | string |
professional_id | uuid |
Recusa
| Campo | Tipo |
|---|---|
code | string |
message | string |
detailsNem sempre vem | object |
As chamadas
Cada uma traz o que recebe, o que devolve e um exemplo pronto para colar no terminal. Troque os identificadores do exemplo pelos seus.
MétodoGETEndereço/v1/appointments
Lista os agendamentos de um período, em páginas.
- Escopo exigido
appointments:readLer a agenda- Repetição
- Não se aplica
- Resposta
- Agendamento
datanext_cursorPode vir sem valor
| Parâmetro | Tipo | Onde vai |
|---|---|---|
fromOpcional
| date | query |
toOpcional
| date | query |
statusOpcional
| string | query |
professional_idOpcional | uuid | query |
limitOpcional
| integer | query |
cursorOpcional
| string | query |
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments?from=2026-10-01&to=2026-10-31&limit=2"{
"data": [
{
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "agendado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
},
{
"id": "5e0b7a94-1d62-4c38-97af-8b41d2e6c03f",
"status": "confirmado",
"starts_at": "2026-10-03T16:00:00",
"ends_at": "2026-10-03T16:45:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
],
"next_cursor": "MjAyNi0xMC0wM3wxNDozMDowMHw5YzFmNGIyYS03ZTgzLTRkNjEtYjBhNS0yZjhjNmQzMWU0YTc="
}curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments?from=2026-10-01&to=2026-10-31&limit=2&cursor=MjAyNi0xMC0wM3wxNDozMDowMHw5YzFmNGIyYS03ZTgzLTRkNjEtYjBhNS0yZjhjNmQzMWU0YTc%3D"{
"data": [],
"next_cursor": null
}MétodoPOSTEndereço/v1/appointments
Marca um agendamento para um paciente, com um profissional, num horário.
- Escopo exigido
appointments:writeMexer na agenda- Repetição
- Exige valor de repetição
- Resposta
- Agendamento
data
| Parâmetro | Tipo | Onde vai |
|---|---|---|
Idempotency-KeyObrigatório | string | header |
patient_idObrigatório | uuid | body |
professional_idObrigatório | uuid | body |
procedure_idsObrigatório
| array<uuid> | body |
starts_atObrigatório
| datetime | body |
statusOpcional
| string | body |
curl -X POST \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7f3c05a1-9b24-4e6d-8c17-0a5f3d92b4e8" \
-d '{
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"starts_at": "2026-10-03T14:30:00",
"status": "agendado"
}' \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments"{
"data": {
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "agendado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
}curl -X POST \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
-H "Content-Type: application/json" \
-d '{
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"starts_at": "2026-10-03T14:30:00"
}' \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments"{
"error": {
"code": "validation_failed",
"message": "Cabeçalho Idempotency-Key é obrigatório para criar agendamento."
}
}MétodoGETEndereço/v1/appointments/{id}
Abre um agendamento específico.
- Escopo exigido
appointments:readLer a agenda- Repetição
- Não se aplica
- Resposta
- Agendamento
data
| Parâmetro | Tipo | Onde vai |
|---|---|---|
idObrigatório | uuid | path |
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments/9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7"{
"data": {
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "agendado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
}MétodoPATCHEndereço/v1/appointments/{id}/status
Muda a situação de um agendamento, dentro do que é permitido.
- Escopo exigido
appointments:writeMexer na agenda- Repetição
- Seguro repetir
- Resposta
- Agendamento
data
| Parâmetro | Tipo | Onde vai |
|---|---|---|
idObrigatório | uuid | path |
statusObrigatório
| string | body |
curl -X PATCH \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
-H "Content-Type: application/json" \
-d '{
"status": "confirmado"
}' \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments/9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7/status"{
"data": {
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "confirmado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
}curl -X PATCH \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
-H "Content-Type: application/json" \
-d '{
"status": "realizado"
}' \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments/9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7/status"{
"error": {
"code": "status_transition_not_allowed",
"message": "Transição de status não permitida por esta API.",
"details": {
"from": "agendado",
"to": "realizado"
}
}
}MétodoPOSTEndereço/v1/appointments/{id}/cancel
Cancela um agendamento.
- Escopo exigido
appointments:writeMexer na agenda- Repetição
- Seguro repetir
- Resposta
- Agendamento
data
| Parâmetro | Tipo | Onde vai |
|---|---|---|
idObrigatório | uuid | path |
curl -X POST \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments/9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7/cancel"{
"data": {
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "cancelado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
}MétodoGETEndereço/v1/patients/{id}
Abre a ficha básica de um paciente.
- Escopo exigido
patients:readLer paciente- Repetição
- Não se aplica
- Resposta
- Paciente
data
| Parâmetro | Tipo | Onde vai |
|---|---|---|
idObrigatório | uuid | path |
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/patients/4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63"{
"data": {
"id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"name": "Ana Ribeiro",
"phone": "+5511987654321",
"email": "ana.ribeiro@example.com"
}
}MétodoGETEndereço/v1/practitioners
Lista os profissionais da clínica.
- Escopo exigido
catalog:readLer o catálogo- Repetição
- Não se aplica
- Resposta
- Profissional
data
Esta chamada não recebe parâmetros.
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/practitioners"{
"data": [
{
"id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"name": "Dra. Helena Costa",
"specialty": "Dermatologia"
}
]
}MétodoGETEndereço/v1/procedures
Lista os procedimentos do catálogo.
- Escopo exigido
catalog:readLer o catálogo- Repetição
- Não se aplica
- Resposta
- Procedimento
data
Esta chamada não recebe parâmetros.
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/procedures"{
"data": [
{
"id": "2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d",
"name": "Limpeza de pele profunda",
"price": 280,
"duration_minutes": 60
}
]
}MétodoGETEndereço/v1/availability
Mostra os horários livres de um dia, e dá para restringir a um profissional ou a um procedimento.
- Escopo exigido
catalog:readLer o catálogo- Repetição
- Não se aplica
- Resposta
- Horário livre
dateslots
| Parâmetro | Tipo | Onde vai |
|---|---|---|
dateObrigatório
| date | query |
professional_idOpcional | uuid | query |
procedure_idOpcional | uuid | query |
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/availability?date=2026-10-03&procedure_id=2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"{
"date": "2026-10-03",
"slots": [
{
"time": "09:00",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae"
},
{
"time": "10:00",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae"
}
]
}Repetir sem duplicar
A rede cai no meio da chamada, o tempo estoura, e você fica sem saber se o agendamento foi criado. Repetir por conta própria pode marcar o mesmo paciente duas vezes.
Por isso toda criação viaja com um valor de repetição inventado por você, um para cada operação. Se ele chegar de novo com o mesmo conteúdo, a Meevia devolve a resposta que já tinha dado, sem processar outra vez.
Idempotency-Key
Como escolher esse valor
Gere um valor único por operação (um identificador aleatório serve) e guarde esse valor junto da sua tentativa, para reusar exatamente o mesmo na hora de repetir. Gerar um novo a cada tentativa é o mesmo que não ter proteção nenhuma.
A resposta guardada volta como veio, inclusive quando ela foi uma recusa. Repetir com o valor de uma tentativa que deu errado devolve o mesmo erro, não uma tentativa nova.
Reusar o mesmo valor com conteúdo diferente é recusado, e essa recusa costuma denunciar duas operações distintas compartilhando o mesmo valor. A mesma resposta aparece quando uma chamada gêmea ainda está em andamento, e aí esperar alguns instantes e repetir resolve.
O valor vale por um dia. Depois disso ele é esquecido, e uma repetição volta a processar de verdade.
Uma tentativa que ficou sem resposta é dada por perdida depois de poucos minutos, e a chamada seguinte com aquele valor assume o lugar. Assim uma requisição que morreu no meio não trava você até o dia seguinte.
- Minutos de espera antes de repetir uma tentativa sem resposta
5
O que acontece ao repetir cada chamada
Não se aplica
É leitura, e leitura não muda nada ao ser repetida.
Exige valor de repetição
Sem ele a chamada é recusada. É a proteção contra marcar o mesmo paciente duas vezes quando a rede falha no meio.
Seguro repetir
Repetir leva ao mesmo lugar: pedir a situação em que o agendamento já está devolve o agendamento como ele está. Não é preciso enviar valor de repetição aqui.
Limites de uso
Cada chave tem o próprio teto de chamadas por minuto. É por chave e não por clínica. Duas integrações na mesma clínica não disputam o mesmo limite, e uma que disparou chamadas demais não derruba a outra.
- Chamadas por minuto, em cada chave
120
A contagem zera na virada de cada minuto do relógio, e não numa janela que desliza. Na prática, dois blocos disparados na virada caem em minutos diferentes, então um pico curto pode passar mesmo somando acima do teto. Não é folga com que dê para contar: o que sustenta uma integração é o ritmo médio.
Quando estourar, a resposta traz num cabeçalho próprio, e não no corpo, quantos segundos esperar. Respeite esse número em vez de tentar de novo na hora. Se isso virar rotina, o problema não é o teto: espace as chamadas, guarde o que muda pouco (o catálogo muda pouco) e evite ficar perguntando em laço.
Retry-After
Mudanças de situação permitidas
A API aceita um conjunto fechado de mudanças, e a tabela mostra quais: cada situação de origem tem os destinos que ela permite, e o que não está na tabela é recusado. Concluir e registrar falta ficam fora por decisão de produto. As duas geram venda, cobrança e consumo de sessão de pacote. Continuam na mão de quem opera a clínica.
| Situação atual | Pode mudar para |
|---|---|
pre_agendado | agendadoconfirmadocancelado |
agendado | confirmadocancelado |
confirmado | cancelado |
em_espera | cancelado |
As situações
pre_agendado- Marcado, mas ainda sem confirmação de ninguém. É a situação em que um agendamento novo nasce quando você não pede outra.
agendado- Está na agenda e a clínica conta com ele.
confirmado- O paciente confirmou que vem. É o que a recepção olha para saber com o que contar no dia.
em_espera- Está na fila, esperando uma vaga abrir. A API não coloca ninguém aqui, mas lê quem está, e daqui a única mudança possível é cancelar.
cancelado- Cancelado, e é ponto final: daqui a API não muda mais nada.
realizado- O atendimento aconteceu. Quem grava isso é a clínica, porque a mudança gera a venda. A API lê e não escreve.
faltou- O paciente não apareceu. Também é da clínica: entra na cobrança de falta e no consumo de sessão de pacote. A API lê e não escreve.
Quando a chamada não dá certo
Toda recusa volta no mesmo formato, com um código curto que não muda e uma mensagem em português. No seu programa, decida sempre pelo código, nunca pela mensagem: ela existe para o seu log e pode ser reescrita a qualquer momento.
Algumas recusas trazem também o detalhamento do que não passou. Nem toda recusa traz esse detalhamento, então o seu código não pode depender dele.
plan_requiredCódigo de status 403
A chave é válida, mas o plano da clínica não inclui o acesso à API.
Nenhuma mudança no seu código resolve. Avise a clínica, que fala com o suporte da Meevia: é assunto de plano.
scope_requiredCódigo de status 403
A chave é válida, mas não tem o escopo que esta chamada exige.
Veja, na ficha da chamada, qual escopo ela pede, e compare com os escopos da chave na aba Chaves do painel. Escopo não se edita: emita outra chave com o que falta, troque no seu ambiente e revogue a antiga.
not_foundCódigo de status 404
Duas situações diferentes chegam aqui: ou o endereço não corresponde a nada, ou o que você pediu não existe nesta clínica.
Confira primeiro o endereço, letra por letra, contra o exemplo da chamada; um plural a mais cai neste caso. Se o endereço estiver certo, o que falta é o registro: ele pode ter sido apagado, ou ser de outra clínica. Lembre também que o ambiente de teste tem os dados dele próprio. Identificador copiado da clínica real não existe lá dentro.
method_not_allowedCódigo de status 405
O endereço existe, mas não atende esse tipo de requisição.
Confira, na ficha da chamada, qual método ela espera. Quase sempre é uma leitura tentada como escrita, ou o contrário.
validation_failedCódigo de status 422
Alguma coisa no que você enviou não passou na conferência: falta um dado obrigatório, ou um deles veio num formato que não serve.
A mensagem da recusa diz o que não passou. Compare com a tabela de parâmetros da chamada, com atenção especial ao formato de data e hora, que é onde mais se erra.
rate_limitedCódigo de status 429
Você passou do teto de chamadas por minuto dessa chave.
Espere os segundos que vêm no cabeçalho de espera da resposta. Ele não está no corpo. É por isso que muita gente não acha o número e acaba tentando de novo na hora, o que só afunda mais. Se acontecer com frequência, ajuste o ritmo: espace as chamadas, guarde o que muda pouco e não fique perguntando em laço.
idempotency_conflictCódigo de status 409
O valor de repetição que você enviou já foi usado para outra coisa, ou uma chamada gêmea ainda está em andamento.
Se foi outra coisa, passe a gerar um valor novo para cada operação nova; reaproveitar o mesmo em operações diferentes é o que causa isto. Se for a gêmea, espere alguns instantes e repita com o mesmo valor: assim que a primeira terminar, a resposta guardada é devolvida.
status_transition_not_allowedCódigo de status 422
A mudança que você pediu não é permitida a partir da situação em que o agendamento está.
Leia a tabela de mudanças permitidas, que mostra para onde dá para ir a partir de cada situação. Concluir e registrar falta não estão lá, e continuam sendo da operação da clínica. A recusa vem com a situação atual e a pedida, o que costuma revelar que o agendamento já estava noutro estado.
sandbox_not_readyCódigo de status 409
A chave é de teste e o ambiente de teste da clínica ainda não está de pé.
Repita em alguns instantes. Se insistir, o ambiente precisa ser reiniciado, o que o recria do zero, e isso você mesmo faz se tem Pode administrar no painel. Chave de produção nunca cai neste caso.
internal_errorCódigo de status 500
Alguma coisa quebrou do nosso lado.
Não é o seu código. Tente de novo depois de um intervalo. Se persistir, fale com o suporte da Meevia dizendo o horário e o que você chamou; a aba Requisições do painel ajuda a localizar.
Precisa de ajuda
Conte o que você chamou, o que esperava e o que voltou. A aba Requisições do painel mostra o que chegou até nós, e é por ele que a gente começa a olhar.
Esta página e a API
Se você encontrar diferença entre o que está escrito aqui e o que a API respondeu, a API tem razão, e a gente quer saber. A data abaixo diz quando esta página foi conferida contra ela pela última vez.