Skip to navigation

Agendamento

Um agendamento é o compromisso marcado entre um paciente e um profissional: quando, com quem, e se é online ou presencial. No Nilo Care ele aparece na ficha do paciente, nas seções Agendamentos liberados e Agendamentos marcados — e, nas implantações com a tela nova, também em Passados.

No FHIR o recurso é o Appointment, e esta integração o usa nas duas pontas.

Dois campos do FHIR se cruzam aqui, e é fácil errar. O título do agendamento vai em description, e as observações vão em comment — não o contrário. Trocá-los grava o texto livre no campo de título da plataforma.

Nenhum dos dois é exibido nas telas de agendamento hoje: o que a equipe vê na lista é o nome do profissional e a especialidade. Mas eles ficam gravados, e é pelo nome certo que outros sistemas os leem.

Campos

A coluna No Nilo Care traz o rótulo com que o dado aparece para a equipe; são rótulos, não caminhos de navegação.

CampoObrigatórioO que significaNo Nilo Care
resourceTypesimConstante Appointment—
identifiersimSuas chaves do agendamento. É por elas que a API decide entre criar e atualizar—
statussimA situação. Oito valores aceitos, quatro situações — veja abaixoa seção onde o agendamento aparece
startsim na escritaInício previstoa data e a hora na linha do agendamento
endsim na escritaFim previsto. Tem de ser maior que o starta hora final, na mesma linha
participantsimExatamente um paciente e um profissionalSelecione o profissional responsável
descriptionnãoO título do agendamento— (não é exibido)
commentnãoAs observações, em texto livre— (não é exibido)
appointmentTypenãoModalidade: online ou presencialConsulta será
extension appointment-allowConflictnãoDispensa a conferência da agenda do profissional ao gravar. Ausente vale true—
creatednãoSó resposta: quando o agendamento foi criado—
contained[]nãoSó resposta: a sala de vídeo, quando há—
id · metanãoSó resposta: identificador Nilo FHIR e metadados da gravação—

Sobreposição de horário

A plataforma sabe conferir a agenda do profissional antes de gravar: o horário não pode colidir com outro compromisso, e precisa estar dentro dos horários em que ele atende. Pela integração essa conferência não roda por padrão. Um Appointment que chega sem a extensão appointment-allowConflict é gravado como se ela viesse com valueBoolean: true — o horário que você enviou é tratado como decisão já tomada do seu lado.

Mandar a extensão com true explicita o que já é o padrão:

POST
/fhir/resources/Appointment
curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Appointment \
-H "x-api-key: <apiKey>" \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Appointment",
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/agendamento/",
"value": "AG-3003",
"use": "usual"
}
],
"status": "booked",
"participant": [
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709",
"use": "usual"
},
"type": "Patient"
},
"status": "accepted"
},
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932",
"use": "usual"
},
"type": "Practitioner"
},
"status": "accepted"
}
],
"start": "2026-06-16T11:00:00+00:00",
"end": "2026-06-16T11:20:00+00:00",
"description": "Encaixe — cardiologia",
"extension": [
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/appointment-allowConflict",
"valueBoolean": true
}
]
}'

Para pedir a conferência num agendamento, envie a extensão com valueBoolean: false — com a ressalva do terceiro aviso abaixo.

true dispensa mais do que a colisão de horário. Com ele, a plataforma para de conferir a agenda daquele agendamento por inteiro — e passam também:

  • horários fora da grade de atendimento do profissional, que a conferência recusa ainda que não colidam com nada;
  • um segundo agendamento do mesmo paciente no mesmo horário, e um segundo agendamento do mesmo profissional no mesmo horário, que a conferência barra como duplicidade.

Como true é o padrão, é disso que você abre mão em cada agendamento enviado, e são as três juntas — não há como dispensar uma e manter as outras.

Um agendamento gravado com true deixa de bloquear os outros. Ele não entra na conferência de horário dos agendamentos seguintes: um agendamento comum, marcado depois no mesmo horário, é aceito como se o primeiro não existisse — e é aceito sem extensão nenhuma.

O efeito não termina naquela chamada, e true é o padrão: cada agendamento que você envia degrada a conferência de agenda para todo mundo que marca depois, inclusive pela tela.

false não é o contrário de true aqui. Ele não recusa a sobreposição: deixa a decisão para a configuração de sobreposição do seu care provider. Se essa configuração está habilitada, a sobreposição continua permitida e a resposta devolve true — não há como recusá-la agendamento por agendamento. Para desabilitá-la, fale com o time de suporte.

Na atualização, omitir a extensão não preserva o false anterior. O padrão vale em toda escrita, não só na criação: um update que chega sem a extensão sobrescreve com true o false gravado antes. Para manter o false, reenvie-o em cada update daquele agendamento.

Uma extensão com a URL errada, ou cujo valor não venha em valueBoolean, é ignorada — e ignorada vale true. Um false escrito errado não recusa nada, e não há erro avisando: confira a URL antes de concluir que a conferência está valendo.

A extensão vem em toda leitura de Appointment, com true ou com false — não só nos agendamentos que a usaram na escrita. Um false na resposta significa “a conferência de agenda valeu para este agendamento”, não “você mandou false”.

A URL completa da extensão está em Extensões — aqui ela aparece só pelo nome final.

status: oito valores entram, seis saem

A escrita aceita oito valores do FHIR e os reduz a quatro situações da plataforma. A leitura devolve a situação, não o que você mandou:

Você enviaA plataforma registraA leitura devolve
booked · proposed · pending · arrived · checked-inAgendadobooked
cancelledCanceladocancelled
noshowPaciente não compareceunoshow
fulfilledRealizadofulfilled

A leitura, por sua vez, traduz nove situações da plataforma em seis códigos:

Situação no Nilo Carestatus
Agendadobooked
Reagendadobooked
Recorrentebooked
Liberadoproposed
Canceladocancelled
Não compareceunoshow
Não compareceu, com justificativanoshow
Bloqueado / indisponívelwaitlist
Realizadofulfilled

Um agendamento reagendado e um recorrente voltam como booked, iguais a um agendamento comum. Não há campo que diga que ele foi remarcado, nem que ele faz parte de uma série.

O status não faz round-trip. Enviar proposed, pending, arrived ou checked-in e reler devolve booked — os quatro colapsam na mesma situação. Não construa fluxo em cima de distinguir “confirmado” de “paciente chegou”: a plataforma não guarda essa diferença.

waitlist e entered-in-error recusam a chamada. Eles não têm destino na plataforma, e a recusa vem como not-supported, apontando Appointment.status.

E waitlist é justamente um valor que a leitura devolve, num agendamento marcado como indisponível pela equipe. Ou seja: há agendamentos que você lê e não consegue reenviar.

proposed é aceito na escrita, mas não faz o que parece: ele não cria um agendamento liberado, vira um agendamento normal. Liberar horário para o paciente marcar é ação da equipe na tela.

waitlist é o único valor que a leitura devolve e a escrita não aceita.

Os participantes

participant precisa de exatamente um de cada tipo, e o type do actor é o que distingue:

"participant": [
{ "status": "accepted",
"actor": { "type": "Patient",
"identifier": { "system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709" } } },
{ "status": "accepted",
"actor": { "type": "Practitioner",
"identifier": { "system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932" } } }
]

Zero ou dois participantes do mesmo tipo recusam a chamada, com uma mensagem que nomeia o tipo que faltou. Um agendamento com dois profissionais, ou sem paciente, não é possível.

E o type é obrigatório: sem ele a API não sabe qual é qual, e a chamada é recusada como se o participante não existisse.

participant[].status é exigido pelo FHIR e descartado na escrita: a leitura devolve sempre accepted, nos dois participantes. Não há como registrar que o paciente ainda não confirmou.

A modalidade

appointmentType diz se a consulta é online ou presencial, num coding cujo system é {host}/fhir/resources/CodeSystem/appointment-type — a URL absoluta do seu ambiente, como https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/appointment-type em produção:

codeModalidade
ONLINEAtendimento online
IN_PERSONAtendimento presencial

Omitir appointmentType cria um agendamento online, não um sem modalidade. Se a consulta é presencial, mande o IN_PERSON — a omissão não é neutra.

Um coding em outro system é ignorado em silêncio e cai na mesma regra da omissão — e é por isso que errar a URL do system é perigoso: a consulta presencial vira online e a chamada responde 200. Já um código desconhecido dentro do system da Nilo recusa a chamada com not-supported.

A sala de vídeo

Nos agendamentos online com sala criada, o link vem embutido no próprio recurso, em contained[0].address:

"contained": [
{ "resourceType": "Endpoint",
"status": "active",
"address": "https://video.nilo.services/r/9f2c41a8",
"connectionType": { "code": "https" },
"payloadType": [{ "text": "video" }] }
]

É só resposta: enviar um contained não cria sala — embora o que você mandar fique gravado e volte nas leituras seguintes, sem significar nada.

A sala não nasce com o agendamento, e nem todo agendamento tem uma. Três coisas precisam ser verdade:

  • a funcionalidade tem de estar habilitada para o seu ambiente, o que é decidido na implantação. Se ela não estiver, nenhum agendamento terá sala — fale com o Suporte;
  • o agendamento tem de ter datas no futuro: um agendamento retroativo não gera sala;
  • a situação tem de ser de agendamento em aberto: fulfilled, noshow e cancelled não geram sala.

E a criação é assíncrona. A resposta do POST normalmente vem sem contained; a sala aparece em segundos, podendo levar alguns minutos em períodos de alta demanda. Prefira ser avisado por webhook a ficar consultando — e não conclua que o agendamento não terá sala só porque a primeira leitura veio sem ela.

Campos que a Nilo não usa

O Appointment canônico traz muito mais do que esta integração lê: cancelationReason, serviceCategory, serviceType, specialty, reasonCode, reasonReference, priority, supportingInformation, minutesDuration, slot, basedOn, requestedPeriod e patientInstruction. Nenhum deles é lido.

Repare em cancelationReason: não há como registrar por que um agendamento foi cancelado. E em specialty: a especialidade do agendamento existe na tela e não tem campo aqui.

A referência lista só os campos suportados, e é assim que ela deve ser lida: o que mandar na escrita. A API em si é mais tolerante — o que você mandar a mais fica guardado no recurso e volta nas leituras seguintes, sem nunca ter significado nada para a plataforma. Se o seu validador for estrito contra a referência, uma resposta assim vai parecer inválida; o remédio é não enviá-los.

Marcar um agendamento

Requisição — Agendar uma consulta online
{
"resourceType": "Appointment",
"identifier": [
{
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/agendamento/",
"value": "AG-3001"
}
],
"status": "booked",
"description": "Consulta de retorno — endocrinologia",
"comment": "Paciente pediu horário no fim da tarde.",
"start": "2026-06-15T14:00:00+00:00",
"end": "2026-06-15T14:30:00+00:00",
"appointmentType": {
"coding": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/appointment-type",
"code": "ONLINE"
}
]
},
"participant": [
{
"status": "accepted",
"actor": {
"type": "Patient",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709"
}
}
},
{
"status": "accepted",
"actor": {
"type": "Practitioner",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932"
}
}
}
]
}

A resposta é o recurso gravado, sem envelope:

Response
{
"resourceType": "Appointment",
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--scheduling-v2",
"value": "620914",
"use": "usual"
},
{
"system": "https://www.acmesaude.com.br/integracao/agendamento/",
"value": "AG-3001",
"use": "usual"
}
],
"status": "booked",
"participant": [
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709",
"use": "usual"
},
"type": "Patient",
"reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
},
"status": "accepted"
},
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932",
"use": "usual"
},
"type": "Practitioner",
"reference": "Practitioner/1f30c8b7-45ad-4e62-9c81-73b0e5f24a19"
},
"status": "accepted"
}
],
"id": "8f30c26b-5d17-4e94-a1c3-70b6e2854f19",
"meta": {
"lastUpdated": "2026-06-01T09:12:45.208000Z",
"versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
},
"start": "2026-06-15T14:00:00+00:00",
"end": "2026-06-15T14:30:00+00:00",
"description": "Consulta de retorno — endocrinologia",
"comment": "Paciente pediu horário no fim da tarde.",
"appointmentType": {
"coding": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/appointment-type",
"code": "ONLINE",
"display": "Atendimento Online"
}
]
},
"extension": [
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/appointment-allowConflict",
"valueBoolean": false
}
],
"created": "2026-06-01T09:12:44+00:00"
}

Guarde o id: é por ele que se faz a leitura direta. Ao lado do seu identifier, a resposta traz o identificador Nilo do agendamento, no system …/NamingSystem/care-api--scheduling-v2.

Requisição — Agendar uma consulta presencial
{
"resourceType": "Appointment",
"identifier": [
{
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/agendamento/",
"value": "AG-3002"
}
],
"status": "booked",
"description": "Consulta inicial — nutrição",
"start": "2026-06-16T09:00:00+00:00",
"end": "2026-06-16T09:40:00+00:00",
"appointmentType": {
"coding": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/appointment-type",
"code": "IN_PERSON"
}
]
},
"participant": [
{
"status": "accepted",
"actor": {
"type": "Patient",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709"
}
}
},
{
"status": "accepted",
"actor": {
"type": "Practitioner",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932"
}
}
}
]
}

Cancelar

Cancelar é reenviar o mesmo identifier com status: cancelled.

Requisição — Cancelar um agendamento
{
"resourceType": "Appointment",
"identifier": [
{
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/agendamento/",
"value": "AG-3001"
}
],
"status": "cancelled",
"description": "Consulta de retorno — endocrinologia",
"comment": "Paciente pediu horário no fim da tarde.",
"start": "2026-06-15T14:00:00+00:00",
"end": "2026-06-15T14:30:00+00:00",
"appointmentType": {
"coding": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/appointment-type",
"code": "ONLINE"
}
]
},
"participant": [
{
"status": "accepted",
"actor": {
"type": "Patient",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709"
}
}
},
{
"status": "accepted",
"actor": {
"type": "Practitioner",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932"
}
}
}
]
}

Não há atualização parcial. Todo POST monta o agendamento inteiro a partir do payload, e o que você omitir é apagado na plataforma ou volta ao padrão: sem comment, as observações somem da ficha; sem appointmentType, um agendamento presencial vira online.

Reenvie o recurso inteiro em toda atualização, inclusive no cancelamento.

E a leitura não acompanha esse apagamento. O recurso FHIR guarda o último valor não vazio: depois de um POST sem comment, a consulta continua devolvendo a observação antiga, que a equipe já não vê. Para zerar de verdade os dois lados, mande o campo vazio ("comment": "") em vez de omiti-lo.

Não há remoção por integração: este endpoint nunca responde 204. Cancelar é a forma de encerrar um agendamento.

Ao cancelar, a plataforma pode limpar as datas do registro. Um agendamento com status: cancelled lido depois disso pode vir sem start e sem end — não trate a ausência como erro de leitura.

Buscar

GET
/fhir/resources/Appointment
curl -G https://landing-zone-api.nilo.services/fhir/resources/Appointment \
-H "x-api-key: <apiKey>" \
-d _count=50 \
-d _lastUpdated=eq2013-01-14 \
--data-urlencode appointment-type=https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/appointment-type|ONLINE \
-d date=ge2026-06-01 \
--data-urlencode identifier=https://www.acmesaude.com.br/integracao/agendamento/|AG-3001 \
--data-urlencode patient=Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4 \
--data-urlencode patient:identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709 \
--data-urlencode practitioner=Practitioner/1f30c8b7-45ad-4e62-9c81-73b0e5f24a19 \
--data-urlencode practitioner:identifier=https://www.acmesaude.com.br/integracao/profissional/|5032932 \
-d status=booked

A resposta é sempre um Bundle do tipo searchset:

Response
{
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{
"fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Appointment/8f30c26b-5d17-4e94-a1c3-70b6e2854f19",
"resource": {
"resourceType": "Appointment",
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--scheduling-v2",
"value": "620914",
"use": "usual"
},
{
"system": "https://www.acmesaude.com.br/integracao/agendamento/",
"value": "AG-3001",
"use": "usual"
}
],
"status": "booked",
"participant": [
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709",
"use": "usual"
},
"type": "Patient",
"reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
},
"status": "accepted"
},
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932",
"use": "usual"
},
"type": "Practitioner",
"reference": "Practitioner/1f30c8b7-45ad-4e62-9c81-73b0e5f24a19"
},
"status": "accepted"
}
],
"id": "8f30c26b-5d17-4e94-a1c3-70b6e2854f19",
"meta": {
"lastUpdated": "2026-06-01T09:12:45.208000Z",
"versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
},
"start": "2026-06-15T14:00:00+00:00",
"end": "2026-06-15T14:30:00+00:00",
"description": "Consulta de retorno — endocrinologia",
"comment": "Paciente pediu horário no fim da tarde.",
"appointmentType": {
"coding": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/appointment-type",
"code": "ONLINE",
"display": "Atendimento Online"
}
]
},
"created": "2026-06-01T09:12:44+00:00",
"contained": [
{
"resourceType": "Endpoint",
"address": "https://video.nilo.services/r/9f2c41a8",
"status": "active",
"connectionType": {
"code": "https"
},
"payloadType": [
{
"text": "video"
}
]
}
]
},
"search": {
"mode": "match"
}
},
{
"fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Appointment/1d74b8e0-92a6-4c15-830f-4e5a7c93d268",
"resource": {
"resourceType": "Appointment",
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--scheduling-v2",
"value": "620915",
"use": "usual"
}
],
"status": "fulfilled",
"participant": [
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709",
"use": "usual"
},
"type": "Patient",
"reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
},
"status": "accepted"
},
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932",
"use": "usual"
},
"type": "Practitioner",
"reference": "Practitioner/1f30c8b7-45ad-4e62-9c81-73b0e5f24a19"
},
"status": "accepted"
}
],
"id": "1d74b8e0-92a6-4c15-830f-4e5a7c93d268",
"meta": {
"lastUpdated": "2026-06-02T11:40:02.774000Z",
"versionId": "MTc4NjAyMTQ1MjkwNTAwMDM5OA"
},
"start": "2026-06-02T10:00:00+00:00",
"end": "2026-06-02T10:40:00+00:00",
"description": "Consulta inicial — nutrição",
"appointmentType": {
"coding": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/appointment-type",
"code": "IN_PERSON",
"display": "Atendimento Presencial"
}
]
},
"created": "2026-05-20T15:03:11+00:00"
},
"search": {
"mode": "match"
}
}
],
"link": []
}

Busca sem resultados não é erro: volta 200 com um Bundle cujo entry é uma lista vazia.

Response
{
"resourceType": "Bundle",
"type": "searchset",
"entry": [],
"link": []
}

Parâmetros de busca suportados

NomeTipoDescriçãoExpressão
identifiertokenIdentificador do agendamento, em system|valueAppointment.identifier
patientreferencePaciente, pelo id Nilo FHIR deleAppointment.participant.actor
patient:identifierreferencePaciente, pelo identificador deleAppointment.participant.actor.identifier
practitionerreferenceProfissional, pelo id Nilo FHIR deleAppointment.participant.actor
practitioner:identifierreferenceProfissional, pelo identificador deleAppointment.participant.actor.identifier
datedateData do agendamento, com os prefixos eq, ge, leAppointment.start
statustokenSituaçãoAppointment.status
appointment-typetokenModalidade, em system|codeAppointment.appointmentType
_lastUpdateddateData da última gravação no store, com os prefixos eq, ge, le—

Os demais parâmetros canônicos do Appointment — service-category, service-type, specialty, reason-code, reason-reference, slot, based-on e supporting-info — só encontram o que você mesmo tiver enviado: a plataforma não preenche nenhum desses campos, mas guarda o que vier no payload.

part-status é a exceção pelo motivo oposto: como todo participante é gravado como accepted, part-status=accepted devolve tudo. Não é filtro útil.

Qual identificador as referências de participant.actor carregam depende da sua implantação. Na configuração que usa identificadores externos, cada referência sai com o identificador do seu sistema; sem ela, vem o identificador Nilo do paciente e do profissional. É esse system que você tem de usar no filtro. Confira numa resposta de leitura qual dos dois está lá antes de montar a busca em volume.

A paginação é por _count e _page_token; havendo página seguinte, o Bundle traz a URL pronta em link.

Ler por ID

GET
/fhir/resources/Appointment/:id
curl https://landing-zone-api.nilo.services/fhir/resources/Appointment/id \
-H "x-api-key: <apiKey>"

Diferente da busca, esta leitura não devolve um Bundle — mas também não devolve o recurso nu. A resposta é um envelope com fullUrl, search e resource, e o agendamento está em resource. Ler start ou participant na raiz da resposta não encontra nada.

Response
{
"fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Appointment/8f30c26b-5d17-4e94-a1c3-70b6e2854f19",
"resource": {
"resourceType": "Appointment",
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--scheduling-v2",
"value": "620914",
"use": "usual"
}
],
"status": "booked",
"participant": [
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709",
"use": "usual"
},
"type": "Patient",
"reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
},
"status": "accepted"
},
{
"actor": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932",
"use": "usual"
},
"type": "Practitioner",
"reference": "Practitioner/1f30c8b7-45ad-4e62-9c81-73b0e5f24a19"
},
"status": "accepted"
}
],
"id": "8f30c26b-5d17-4e94-a1c3-70b6e2854f19",
"meta": {
"lastUpdated": "2026-06-01T09:12:45.208000Z",
"versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
},
"start": "2026-06-15T14:00:00+00:00",
"end": "2026-06-15T14:30:00+00:00",
"description": "Consulta de retorno — endocrinologia",
"created": "2026-06-01T09:12:44+00:00"
},
"search": {
"mode": "match"
}
}

Efeitos colaterais

Um agendamento apagado na plataforma some do store. A busca para de devolvê-lo e a leitura por id passa a responder 404, sem aviso. Não conclua que ele foi cancelado — um cancelamento devolve status: cancelled, não um 404.

O mesmo acontece, mais raramente, quando o agendamento fica sem situação registrada ou com uma situação que esta integração não conhece: o recurso é removido em silêncio na sincronização seguinte.

Marcar um agendamento não cria um atendimento. O atendimento nasce quando a consulta acontece — veja Atendimentos.

O profissional que você informa em participant fica registrado também como autor e como responsável pelo agendamento na plataforma. Não há como separar quem atende de quem marcou.

Um agendamento marcado por integração aparece na agenda do profissional como qualquer outro, e a equipe pode alterá-lo por lá. Uma alteração feita na tela chega às suas leituras seguintes.

Erros

Recusa é 400, e o corpo é um OperationOutcome: issue[].expression aponta o campo culpado e issue[].details.text explica o motivo. A exceção é o 409 da agenda duplicada.

StatuscodeexpressionMensagemQuando
400requiredAppointment.identifierField is requiredO payload não tem identifier
400business-ruleAppointment.identifierUnable to use any of the provided identifiers to match an existing resource, which can lead to duplicates.Há identifier, mas nenhum utilizável
400requiredAppointment.participant.actorAppointment must have only one participant.actor of type PatientFalta o paciente, ou vem mais de um
400requiredAppointment.participant.actorAppointment must have only one participant.actor of type PractitionerFalta o profissional, ou vem mais de um
400not-foundAppointment.participant.actorUnable to find Patient · Unable to find PractitionerO identificador não resolve para alguém do seu ambiente
400requiredAppointment.startThe start field is requiredO payload não tem start
400requiredAppointment.endThe end field is requiredO payload não tem end
400invalidAppointment.endThe end field must be greater than the start fieldO fim é menor ou igual ao início
400not-supportedAppointment.statusThe status '…' is not supportedwaitlist ou entered-in-error
400not-supportedAppointment.appointmentTypeThe appointment type code '…' is not supportedCódigo de modalidade desconhecido no system da Nilo
400structure—Resource has identifier from a Nilo environment that is not the current environment.O payload traz um identificador Nilo gerado em outro ambiente
400structureo campo recusadomensagem da validação FHIRO payload não é um Appointment válido — status ou participant ausentes, tipo errado num campo
400exception—HTTPBadRequest: …O horário colide com outro compromisso do profissional, ou está fora da grade de atendimento dele
409conflict—Resource conflicts with other existing resource(s), mais um diagnosticsJá existe agendamento do mesmo paciente, ou do mesmo profissional, começando naquele horário

As duas últimas linhas são a conferência de agenda, que a integração dispensa por padrão: elas só aparecem quando o Appointment enviado traz a extensão appointment-allowConflict com false e a configuração de sobreposição do care provider não está habilitada. Nenhuma das duas aponta expression: elas não são validações de um campo do payload, e sim da agenda como um todo.

A linha exception não é uma validação desta API — é uma falha repassada como está, com uma mensagem de erro de linguagem que inclui o endereço interno chamado. O mesmo vale para o diagnostics do 409.

Nada disso é contrato: não tente interpretar o texto, não o exiba para o usuário final e não o registre em log de longa duração. Trate code: exception como “payload recusado, motivo não classificado” e confira o start, o end e o profissional.

Resposta 400 — Participantes fora do formato
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "required",
"expression": [
"Appointment.participant.actor"
],
"details": {
"text": "Appointment must have only one participant.actor of type Practitioner"
}
}
]
}

Os payloads completos estão na aba Referência, em POST /fhir/resources/Appointment.

O que a integração não cobre

  • o motivo do cancelamento;
  • a especialidade e a recorrência do agendamento, que existem na tela;
  • a distinção entre agendamento liberado e marcado na escrita — só na leitura;
  • a confirmação do paciente: participant[].status é sempre accepted;
  • criar a sala de vídeo — ela é criada pela plataforma.

Para a consulta prevista por uma diretriz, que antecede o agendamento, veja Consulta prevista; para o atendimento que acontece depois, Atendimentos.