eMedic Platform — Referencia de la API (1.2.0)

Download OpenAPI specification:

eMedic Platform: [email protected] License: LicenseRef-Proprietary

Contrato de la API de la red: recetas y dispensación, ingesta por correo, adaptadores, identidad y verificación de asegurados, claims y liquidación, financiamiento, órdenes de estudios con visación, webhooks y consumo.

API para emitir recetas médicas desde cualquier sistema clínico y rutearlas a la red de farmacias conectadas, con dispensación granular por línea de medicamento (parcial, en varias farmacias/sucursales, con trazabilidad de lote y caducidad).

Audiencias

  • Clínicas / sistemas emisores: crean recetas (POST /prescriptions), consultan las suyas y las anulan. Reciben webhooks de dispensación.
  • Farmacias: buscan recetas por documento de identidad del paciente, consultan el detalle y registran dispensaciones (POST /prescriptions/{id}/dispensations).

Cómo se conecta un emisor

Hay tres puertas de entrada, de menor a mayor esfuerzo de integración:

  1. Ingesta por correo/documento (POST /intake): el médico manda su PDF de siempre. Cero cambios en el sistema del hospital.
  2. Adaptador (POST /adapters/{adapterId}/prescriptions): el hospital emite en su propio formato (FHIR R4, el suyo) y la plataforma lo traduce.
  3. API nativa (POST /prescriptions): el modelo canónico directo.

Las tres desembocan en el mismo schema canónico y producen la misma receta.

Diseño

  • Los recursos siguen la forma de HL7 FHIR (MedicationRequest, MedicationDispense) sin exigir cumplimiento FHIR completo: nombres y estructura alineados para que una integración estándar futura no requiera rediseño.
  • Diagnósticos codificados con CIE-11 (OMS).
  • Multi-tenant: cada credencial pertenece a una Organización (clínica, farmacia). Una clínica solo ve sus recetas; una farmacia solo ve lo necesario para dispensar.
  • Por privacidad, la búsqueda de recetas por farmacias es solo por documento de identidad del paciente (no por nombre, a diferencia del sistema legado).
  • 100% digital, sin papel: la receta electrónica es el único documento; no existe versión en papel en ningún punto del flujo. La firma del médico admite dos modalidades (signature.type): certificado digital, para quienes lo poseen, o imagen de firma escaneada. Qué modalidad es exigible depende de la normativa de cada país.
  • Minimización de datos hacia farmacias: los diagnósticos CIE-11 y las notas clínicas permanecen en la plataforma y la clínica emisora; la farmacia recibe únicamente lo necesario para dispensar (paciente, médico, medicamentos y firma).
  • El documento original manda: cuando la receta entró por ingesta, el PDF firmado por el médico es el documento autoritativo y se sirve en GET /prescriptions/{id}/document. Los campos estructurados son una extracción derivada — sirven para cargar el sistema de la farmacia sin tipeo, pero ante discrepancia el farmacéutico dispensa mirando el documento.
  • Consumo consultable: la tarifa por receta ruteada se factura sobre los mismos contadores que expone GET /usage.

Autenticación

  • OAuth2 client-credentials con scopes (recomendado para integraciones de servidor), o
  • API key en header X-API-Key (permisos equivalentes a scopes, allowlist de IPs, rate limiting y expiración configurables por llave).

Convenciones

  • JSON UTF-8; fechas en ISO 8601 / RFC 3339 (UTC).
  • Errores con cuerpo uniforme { "error": { "code", "message", "details" } }.
  • Escrituras de creación aceptan header Idempotency-Key para reintentos seguros.
  • Rate limiting informado en headers X-RateLimit-Limit, X-RateLimit-Remaining.

Recetas

Emisión y consulta de recetas (forma FHIR MedicationRequest).

Emitir una receta

Crea una receta en la plataforma y la hace disponible para la red de farmacias. Pensado para clínicas y sistemas emisores (también lo usa internamente la ingesta por email una vez validada por un humano).

Requiere scope prescriptions:write.

Authorizations:
oauth2apiKey
header Parameters
Idempotency-Key
string <= 128 characters

Clave única elegida por el cliente (UUID recomendado). Reintentar con la misma clave y el mismo cuerpo devuelve la respuesta original sin duplicar la operación.

Request Body schema: application/json
required
externalId
string

ID de la receta en el sistema emisor (único por organización).

required
object (Patient)

Datos mínimos del paciente (forma FHIR Patient, desnormalizados en la receta).

required
object (Practitioner)

Profesional prescriptor (forma FHIR Practitioner).

Array of objects (Diagnosis)

Diagnósticos CIE-11. Permanecen en la plataforma y la clínica emisora; nunca se exponen a farmacias.

required
Array of objects (MedicationLineCreate) non-empty
object (Signature)

Firma del médico sobre la receta. Dos modalidades:

  • digital_certificate: firma electrónica con certificado digital del médico. value lleva la firma (base64) y certificate el certificado público para verificación. Validez legal plena donde el país la reconozca.
  • scanned_image: imagen de la firma manuscrita escaneada (value, PNG/JPEG en base64). Identifica visualmente al médico; su suficiencia legal depende de la normativa local.
notes
string

Notas para la farmacia (no clínicas).

usesAllowed
integer [ 1 .. 24 ]
Default: 1

Utilizaciones autorizadas por el médico. Default 1: un solo uso — agotadas las cantidades, la receta no puede volver a dispensarse. Un valor mayor la hace recurrente (p. ej. 3 retiros mensuales para un tratamiento crónico): cada utilización habilita de nuevo quantityPrescribed en cada línea.

expiresAt
string <date-time>

Vencimiento de la receta. Si se omite, aplica el default de la plataforma (30 días, a validar con partners).

Responses

Request samples

Content type
application/json
{
  • "externalId": "REC-0142-2026",
  • "patient": {
    },
  • "practitioner": {
    },
  • "diagnoses": [
    ],
  • "medications": [
    ],
  • "signature": {
    },
  • "expiresAt": "2026-09-25T00:00:00Z"
}

Response samples

Content type
application/json
{
  • "id": "rx_01J8ZC4Q9M",
  • "externalId": "string",
  • "status": "active",
  • "issuer": {
    },
  • "patient": {
    },
  • "practitioner": {
    },
  • "diagnoses": [],
  • "medications": [
    ],
  • "signature": {
    },
  • "notes": "string",
  • "usesAllowed": 1,
  • "createdAt": "2019-08-24T14:15:22Z",
  • "expiresAt": "2019-08-24T14:15:22Z",
  • "cancelledAt": "2019-08-24T14:15:22Z"
}

Buscar recetas

  • Farmacias (prescriptions:read): requiere patientIdentityNumber (el paciente presenta su documento en mostrador). Devuelve solo recetas dispensables (active o partially_dispensed) salvo que se filtre por estado.
  • Clínicas (prescriptions:write): lista las recetas emitidas por la propia organización; patientIdentityNumber es opcional.
Authorizations:
oauth2apiKey
query Parameters
patientIdentityNumber
string

Documento de identidad del paciente. Obligatorio para farmacias.

status
string (PrescriptionStatus)
Enum: "active" "partially_dispensed" "dispensed" "cancelled" "expired"

Estado de la receta (mapeo FHIR MedicationRequest.status entre paréntesis):

  • active (active): emitida, sin dispensaciones.
  • partially_dispensed (active): al menos una línea con dispensación parcial o total.
  • dispensed (completed): agotada por uso — todas las utilizaciones autorizadas consumidas. Permanece en el histórico del paciente (visible para farmacias y, a futuro, en la app del paciente) pero no puede volver a dispensarse.
  • cancelled (cancelled): anulada por la clínica emisora.
  • expired (stopped): venció expiresAt sin dispensación completa.

Regla de utilizaciones: la receta es de un solo uso por defecto (usesAllowed: 1). El médico puede autorizar explícitamente más utilizaciones (recetas recurrentes); cada una habilita de nuevo las cantidades por línea. Equivale a FHIR dispenseRequest.numberOfRepeatsAllowed (usesAllowed = 1 + repeats).

externalId
string

ID de la receta en el sistema emisor (solo visible para la clínica emisora).

createdFrom
string <date-time>
createdTo
string <date-time>
limit
integer [ 1 .. 100 ]
Default: 50
offset
integer >= 0
Default: 0

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Detalle de una receta

Incluye el estado de dispensación por línea (cantidades dispensadas/restantes y en qué farmacia/sucursal). Requiere prescriptions:read, o prescriptions:write si la consulta la clínica emisora.

Authorizations:
oauth2apiKey
path Parameters
prescriptionId
required
string

ID de la receta en la plataforma (rx_...).

Responses

Response samples

Content type
application/json
{
  • "id": "rx_01J8ZC4Q9M",
  • "externalId": "string",
  • "status": "active",
  • "issuer": {
    },
  • "patient": {
    },
  • "practitioner": {
    },
  • "diagnoses": [],
  • "medications": [
    ],
  • "signature": {
    },
  • "notes": "string",
  • "usesAllowed": 1,
  • "createdAt": "2019-08-24T14:15:22Z",
  • "expiresAt": "2019-08-24T14:15:22Z",
  • "cancelledAt": "2019-08-24T14:15:22Z"
}

Anular una receta

Solo la clínica emisora (prescriptions:write). No se puede anular una receta con dispensaciones registradas (PRESCRIPTION_HAS_DISPENSATIONS); las líneas aún no dispensadas quedan bloqueadas al anular.

Authorizations:
oauth2apiKey
path Parameters
prescriptionId
required
string

ID de la receta en la plataforma (rx_...).

Request Body schema: application/json
optional
reason
string

Motivo de la anulación (queda en auditoría).

Responses

Request samples

Content type
application/json
{
  • "reason": "string"
}

Response samples

Content type
application/json
{
  • "id": "rx_01J8ZC4Q9M",
  • "externalId": "string",
  • "status": "active",
  • "issuer": {
    },
  • "patient": {
    },
  • "practitioner": {
    },
  • "diagnoses": [],
  • "medications": [
    ],
  • "signature": {
    },
  • "notes": "string",
  • "usesAllowed": 1,
  • "createdAt": "2019-08-24T14:15:22Z",
  • "expiresAt": "2019-08-24T14:15:22Z",
  • "cancelledAt": "2019-08-24T14:15:22Z"
}

Documento original de la receta (PDF/imagen)

Devuelve el documento original tal como lo emitió el médico (PDF o imagen), cuando la receta entró por ingesta. Es el documento autoritativo: el farmacéutico dispensa mirándolo. Los datos estructurados de la receta son una extracción derivada, útil para cargar el sistema de la farmacia sin tipeo, pero no reemplazan al documento — ante discrepancia, manda el documento.

Acceso:

  • Clínica emisora: solo el de sus propias recetas.
  • Farmacia: mientras la receta sea dispensable (active o partially_dispensed), o siempre que esa misma farmacia haya registrado una dispensación sobre ella (para su respaldo posterior).

Devuelve 404 si la receta se emitió por API nativa o por adaptador, porque en ese caso no existe documento original: la receta es el dato estructurado.

Authorizations:
oauth2apiKey
path Parameters
prescriptionId
required
string

ID de la receta en la plataforma (rx_...).

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Dispensaciones

Registro de dispensación por línea de medicamento (forma FHIR MedicationDispense).

Registrar una dispensación

Registra la entrega de una o más líneas de la receta por una farmacia. Soporta dispensación parcial: por línea se indica la cantidad entregada, que no puede exceder la restante (QUANTITY_EXCEEDS_REMAINING). Distintas líneas (o el resto de una línea) pueden dispensarse después en otra farmacia o sucursal.

Requiere scope dispensations:write. La operación es atómica: si alguna línea falla la validación, no se registra nada.

Authorizations:
oauth2apiKey
path Parameters
prescriptionId
required
string

ID de la receta en la plataforma (rx_...).

header Parameters
Idempotency-Key
string <= 128 characters

Clave única elegida por el cliente (UUID recomendado). Reintentar con la misma clave y el mismo cuerpo devuelve la respuesta original sin duplicar la operación.

Request Body schema: application/json
required
branchCode
string

Código de la sucursal de la farmacia (registrada en la plataforma).

dispensedBy
required
string

Identificación del profesional que dispensa.

required
Array of objects (DispensationItemCreate) non-empty
paymentMethod
string
Enum: "cash" "card" "insurance" "other"
receiptNumber
string
notes
string

Responses

Request samples

Content type
application/json
{
  • "branchCode": "SUC-CENTRO",
  • "dispensedBy": "Q. F. Laura Ríos",
  • "items": [
    ],
  • "paymentMethod": "cash",
  • "receiptNumber": "F-000123"
}

Response samples

Content type
application/json
{
  • "id": "disp_01J8ZD8N3V",
  • "prescriptionId": "string",
  • "pharmacy": {
    },
  • "dispensedBy": "string",
  • "items": [
    ],
  • "totalAmount": 0,
  • "paymentMethod": "string",
  • "receiptNumber": "string",
  • "notes": "string",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "prescriptionStatus": "active"
}

Historial de dispensaciones de una receta

Authorizations:
oauth2apiKey
path Parameters
prescriptionId
required
string

ID de la receta en la plataforma (rx_...).

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Webhooks

Suscripción a eventos firmados (HMAC-SHA256).

Nueva receta disponible Webhook

Se envía a farmacias suscritas cuando una receta entra en estado active. Todas las entregas de webhooks incluyen los headers:

  • X-Emedic-Event: tipo de evento.
  • X-Emedic-Delivery: ID único de la entrega (para deduplicar reintentos).
  • X-Emedic-Timestamp: epoch en segundos.
  • X-Emedic-Signature: v1= + HMAC-SHA256 hex de "{timestamp}.{cuerpo}" con el secret del endpoint. Rechazar si la firma no coincide o el timestamp tiene más de 5 minutos.

Entregas con reintento y backoff exponencial durante 24 h ante respuestas no 2xx.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Dispensación registrada (parcial o total) Webhook

Se envía a la clínica emisora cada vez que una farmacia registra una dispensación.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Receta completamente dispensada Webhook

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Receta anulada por la clínica emisora Webhook

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Receta expirada sin dispensación completa Webhook

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

El paciente actualizó su teléfono o correo desde su app Webhook

Evento DIRIGIDO a cada clínica que ya le emitió una receta a ese paciente: nadie se entera de un paciente que no atendió. El paciente verifica el dato nuevo antes de que se propague (código de un solo uso al número nuevo), así que lo que llega acá ya está confirmado. El evento no lleva nada clínico: solo cédula y contacto.

data: { patient: { identityType, identityNumber, phone?, email? }, updatedAt }.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Verificación de identidad completada (dirigido a la aseguradora) Webhook

Se envía a la aseguradora dueña del padrón con cada intento (verde o rojo). La familia completa: identity.enrollment.completed, identity.enrollment.revoked, identity.verification.completed y identity.exception.recorded — todos con la misma forma de entrega y firma que el resto de los webhooks. Nunca llevan datos clínicos: cédula, resultado, código y quién operó.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
string
type
string
createdAt
string <date-time>
object

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "identity.verification.completed",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Visación de un ítem decidida (dirigido al emisor) Webhook

La familia de órdenes, toda dirigida y con la misma entrega firmada:

  • order.issued y order.item.review → a la aseguradora (lo emitido contra ella y lo que espera a su auditor).
  • order.item.authorized / order.item.rejected (con motivo), order.fulfilled y result.available → al emisor, al instante. Ningún evento lleva el contenido clínico del resultado: avisan que está disponible y se lee por la API con la credencial propia.
Authorizations:
oauth2apiKey
Request Body schema: application/json
id
string
type
string
createdAt
string <date-time>
object

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "order.item.authorized",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Resultado disponible (dirigido al emisor, en tiempo real) Webhook

El laboratorio cargó el resultado: el médico tratante se entera al instante y el paciente lo ve en su app a la par (y recibe un aviso SMS sin datos clínicos si tiene cuenta). El evento solo referencia (orderId, itemId, studyCode, abnormal, y — si la orden los trajo — practitionerLicense y externalReference para rutear a la bandeja del médico en tu sistema) — el contenido clínico se lee por GET /orders con la credencial del emisor. La marca abnormal permite priorizar sin esperar la lectura.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Turno reservado (y la familia de la agenda) Webhook

Representa a toda la familia de eventos de agendamiento — appointment.booked, appointment.confirmed, appointment.cancelled, appointment.completed y appointment.no_show — todos con el mismo payload y SIEMPRE dirigidos a la clínica dueña de la agenda: así su sistema (HIS, calendario, recordatorios) se sincroniza sin consultar. El data lleva solo appointmentId, practitionerLicense, patientIdentityNumber, startAt, endAt y status — el motivo de consulta y las notas jamás viajan por webhook.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Transcripción lista (o fallida) Webhook

Representa a transcription.completed y transcription.failed, SIEMPRE dirigidos a la clínica dueña y SIN contenido clínico: el data lleva solo transcriptionId, status, durationSeconds y — si se mandaron — practitionerLicense y externalReference para rutear a la bandeja del médico en tu sistema. La nota se lee por GET /transcriptions/{id} con tu credencial.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Análisis de imagen listo (o fallido) Webhook

Representa a imaging.completed e imaging.failed, SIEMPRE dirigidos a la organización dueña y SIN contenido clínico: el data lleva analysisId, status, modality, la urgency sugerida (para priorizar la bandeja del médico sin exponer hallazgos) y — si se mandaron — practitionerLicense y externalReference. El informe se lee por GET /imaging/analyses/{id} con tu credencial.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Registrar un endpoint de webhooks

Registra una URL HTTPS de la organización para recibir eventos. La respuesta incluye el secret (solo se muestra una vez) con el que se firma cada entrega. Requiere scope webhooks:manage.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
url
required
string <uri>

URL HTTPS que recibirá los eventos por POST.

events
required
Array of strings (WebhookEventType) non-empty
Items Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
description
string

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "id": "we_01J8ZE2W7K",
  • "events": [
    ],
  • "description": "string",
  • "secret": "string",
  • "isActive": true,
  • "createdAt": "2019-08-24T14:15:22Z"
}

Listar endpoints de webhooks de la organización

Authorizations:
oauth2apiKey

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Eliminar un endpoint de webhooks

Authorizations:
oauth2apiKey
path Parameters
endpointId
required
string

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Adaptadores

Ingesta desde el modelo propio de cada sistema emisor (EMR/HIS).

Adaptadores de ingesta disponibles

Lista los formatos de origen que la plataforma sabe interpretar. Cada entrada identifica un adaptador (id) que traduce el modelo del sistema emisor al modelo canónico de eMedic.

Authorizations:
oauth2apiKey

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Emitir una receta en el formato propio del emisor

El formato del emisor no es su problema, es el nuestro. El hospital envía la receta tal como la produce su sistema (FHIR R4, el modelo del eMedic original, o el que se le construya) y la plataforma la transforma al modelo canónico.

La puerta final es invariable: el resultado de la transformación se valida contra el mismo schema que POST /prescriptions. Un adaptador nunca puede colar una receta que la API nativa rechazaría. Si la transformación falla o el resultado no valida, la respuesta es 400 VALIDATION_ERROR con details señalando el campo de origen.

El cuerpo es libre: su forma la define el adaptador elegido, no este contrato. Solo organizaciones emisoras; una farmacia recibe 403.

Authorizations:
oauth2apiKey
path Parameters
adapterId
required
string
Examples:
  • fhir-r4 -

ID del adaptador (ver GET /adapters).

header Parameters
Idempotency-Key
string <= 128 characters

Clave única elegida por el cliente (UUID recomendado). Reintentar con la misma clave y el mismo cuerpo devuelve la respuesta original sin duplicar la operación.

Request Body schema: application/json
required

Payload en el formato de origen que el adaptador espera.

property name*
additional property
any

Responses

Request samples

Content type
application/json
{ }

Response samples

Content type
application/json
{
  • "id": "rx_01J8ZC4Q9M",
  • "externalId": "string",
  • "status": "active",
  • "issuer": {
    },
  • "patient": {
    },
  • "practitioner": {
    },
  • "diagnoses": [],
  • "medications": [
    ],
  • "signature": {
    },
  • "notes": "string",
  • "usesAllowed": 1,
  • "createdAt": "2019-08-24T14:15:22Z",
  • "expiresAt": "2019-08-24T14:15:22Z",
  • "cancelledAt": "2019-08-24T14:15:22Z",
  • "adapter": "string"
}

Ingesta

Recetas que llegan por correo o documento, con remitente verificado.

Registrar un médico autorizado a enviar recetas por correo

El registro de remitentes es la identidad del médico en la ingesta por correo: la plataforma no puede validar a un desconocido, así que solo acepta recetas de direcciones dadas de alta por la propia clínica. Lo que el registro dice sobre el médico (nombre, matrícula) tiene prioridad sobre lo que la extracción lea del documento.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
emailAddress
required
string <email>
practitionerName
required
string
practitionerLicense
required
string

Número de registro/matrícula médica.

specialty
string

Responses

Request samples

Content type
application/json
{
  • "emailAddress": "[email protected]",
  • "practitionerName": "string",
  • "practitionerLicense": "string",
  • "specialty": "string"
}

Response samples

Content type
application/json
{
  • "id": "snd_9f3c1a0b2d4e6f8a0b1c",
  • "emailAddress": "[email protected]",
  • "practitionerName": "string",
  • "practitionerLicense": "string",
  • "specialty": "string",
  • "isActive": true,
  • "createdAt": "2019-08-24T14:15:22Z"
}

Listar los médicos autorizados de la organización

Authorizations:
oauth2apiKey

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Dar de baja un remitente autorizado

Baja lógica: el remitente deja de poder emitir, pero las recetas que ya envió conservan su trazabilidad.

Authorizations:
oauth2apiKey
path Parameters
senderId
required
string

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Ingresar una receta en su formato original (correo o documento)

Entrada para recetas que no vienen de una integración: el médico manda un PDF por correo y la clínica (o su gateway de correo) lo deposita aquí.

Puertas de confianza, en orden:

  1. Origen email con senderVerified: false — si el gateway no pudo validar DKIM/SPF/DMARC, el ítem entra pero nunca se auto-aprueba: un correo falsificable no puede emitir recetas a nombre de un médico.
  2. Remitente no registrado — sin alta previa (POST /intake/senders) no hay médico identificable, así que tampoco hay auto-aprobación.
  3. Documento adjunto — la auto-aprobación exige el original: es lo que el farmacéutico va a mirar para dispensar.

La extracción estructurada corre en segundo plano; cuando pasa las puertas, la receta se emite sola y prescriptionId queda apuntando a ella. Cuando no, el ítem se devuelve al médico por correo (rebote) explicando qué corregir — nunca queda esperando revisión humana de eMedic.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
source
string
Default: "api"
Enum: "email" "api"
senderAddress
string <email>

Remitente del correo. Obligatorio si source: email.

senderVerified
boolean

Resultado de DKIM/SPF/DMARC que reporta el gateway de correo. Solo un true aquí habilita la auto-aprobación; nunca lo declara el cliente por conveniencia.

contentType
string
Default: "text"
Enum: "text" "json"
rawContent
string <= 200000 characters

Cuerpo del correo o texto libre de la receta.

Array of objects <= 5 items

Documento original. Hasta 5 adjuntos, ~11 MB cada uno.

Responses

Request samples

Content type
application/json
{
  • "source": "email",
  • "senderAddress": "[email protected]",
  • "senderVerified": true,
  • "contentType": "text",
  • "rawContent": "string",
  • "attachments": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "ink_2c7d1e4f6a8b0c2d4e6f",
  • "source": "email",
  • "contentType": "text",
  • "status": "pending_extraction",
  • "senderAddress": "[email protected]",
  • "senderVerified": true,
  • "attachments": [
    ],
  • "proposal": { },
  • "rawContent": "string",
  • "receivedAt": "2019-08-24T14:15:22Z",
  • "extractedAt": "2019-08-24T14:15:22Z",
  • "reviewedAt": "2019-08-24T14:15:22Z",
  • "reviewedBy": "string",
  • "rejectReason": "string",
  • "prescriptionId": "string"
}

Listar la cola de ingesta de la organización

Authorizations:
oauth2apiKey
query Parameters
status
string
Enum: "pending_extraction" "pending_review" "approved" "rejected"
limit
integer [ 1 .. 100 ]
Default: 50
offset
integer >= 0
Default: 0

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Detalle de un ítem de ingesta

A diferencia del listado, incluye rawContent (el original completo).

Authorizations:
oauth2apiKey
path Parameters
intakeId
required
string

ID del ítem de ingesta (ink_...).

Responses

Response samples

Content type
application/json
{
  • "id": "ink_2c7d1e4f6a8b0c2d4e6f",
  • "source": "email",
  • "contentType": "text",
  • "status": "pending_extraction",
  • "senderAddress": "[email protected]",
  • "senderVerified": true,
  • "attachments": [
    ],
  • "proposal": { },
  • "rawContent": "string",
  • "receivedAt": "2019-08-24T14:15:22Z",
  • "extractedAt": "2019-08-24T14:15:22Z",
  • "reviewedAt": "2019-08-24T14:15:22Z",
  • "reviewedBy": "string",
  • "rejectReason": "string",
  • "prescriptionId": "string"
}

Aprobar un ítem y emitir la receta

Emite la receta a partir de la propuesta extraída. La clínica puede corregirla enviando prescription con el borrador ya arreglado — quien aprueba es la clínica emisora, no eMedic.

Authorizations:
oauth2apiKey
path Parameters
intakeId
required
string

ID del ítem de ingesta (ink_...).

Request Body schema: application/json
required
reviewedBy
required
string

Quién aprueba (queda en auditoría).

object

Borrador corregido; si se omite, se usa la propuesta extraída.

Responses

Request samples

Content type
application/json
{
  • "reviewedBy": "string",
  • "prescription": { }
}

Response samples

Content type
application/json
{
  • "item": {
    },
  • "prescription": {
    }
}

Rechazar un ítem de ingesta

Authorizations:
oauth2apiKey
path Parameters
intakeId
required
string

ID del ítem de ingesta (ink_...).

Request Body schema: application/json
required
reviewedBy
required
string
reason
required
string <= 1000 characters

Responses

Request samples

Content type
application/json
{
  • "reviewedBy": "string",
  • "reason": "string"
}

Response samples

Content type
application/json
{
  • "id": "ink_2c7d1e4f6a8b0c2d4e6f",
  • "source": "email",
  • "contentType": "text",
  • "status": "pending_extraction",
  • "senderAddress": "[email protected]",
  • "senderVerified": true,
  • "attachments": [
    ],
  • "proposal": { },
  • "rawContent": "string",
  • "receivedAt": "2019-08-24T14:15:22Z",
  • "extractedAt": "2019-08-24T14:15:22Z",
  • "reviewedAt": "2019-08-24T14:15:22Z",
  • "reviewedBy": "string",
  • "rejectReason": "string",
  • "prescriptionId": "string"
}

Consumo

Consumo facturable de la organización (cobro por receta ruteada).

Consumo facturable propio del periodo

Transparencia sobre lo que se va a facturar: la plataforma cobra por transacción (modelo de red tipo Surescripts) y esta ruta expone los mismos contadores y tarifas sobre los que se emite la factura. Cada línea incluye el precio que le aplica a la organización según su contrato; una línea con precio nulo es actividad medida sin cargo.

Cada organización ve únicamente el suyo: el organizationId sale de la credencial, nunca de un parámetro, así que no hay forma de consultar el consumo de otra organización. Sin from/to, el periodo es el mes corriente (UTC).

Authorizations:
oauth2apiKey
query Parameters
from
string <date-time>

Inicio del periodo (RFC 3339). Por defecto, el 1 del mes corriente.

to
string <date-time>

Fin del periodo (RFC 3339). Por defecto, ahora.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "period": {
    }
}

Sandbox

Autoservicio de credenciales de prueba (solo en sandbox.api.emedic.la).

Crear credenciales de prueba sin registro previo

Autoservicio del sandbox (sandbox.api.emedic.la): crea una organización de prueba y devuelve una API key emk_test_... lista para usar, sin hablar con nadie de eMedic. Los datos son ficticios y se reinician periódicamente.

Esta ruta solo existe en el sandbox. En producción las credenciales las emite el operador de la plataforma al firmar el contrato.

Request Body schema: application/json
required
organizationName
required
string <= 200 characters
type
required
string
Enum: "clinic" "pharmacy" "laboratory"

Rol que se quiere ensayar; define los permisos de la llave.

Responses

Request samples

Content type
application/json
{
  • "organizationName": "string",
  • "type": "clinic"
}

Response samples

Content type
application/json
{
  • "organization": {
    },
  • "apiKey": "string",
  • "scopes": [
    ],
  • "environment": "sandbox"
}

Identidad

Verificación biométrica de asegurados en la recepción del prestador: padrón, enrolamiento con consentimiento, verificación con código de autorización y log inmutable para el antifraude de la aseguradora.

Verificación de identidad completada (dirigido a la aseguradora) Webhook

Se envía a la aseguradora dueña del padrón con cada intento (verde o rojo). La familia completa: identity.enrollment.completed, identity.enrollment.revoked, identity.verification.completed y identity.exception.recorded — todos con la misma forma de entrega y firma que el resto de los webhooks. Nunca llevan datos clínicos: cédula, resultado, código y quién operó.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
string
type
string
createdAt
string <date-time>
object

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "identity.verification.completed",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Sincronizar el padrón de asegurados (solo la aseguradora dueña)

Alta/actualización masiva del padrón. La clave de cada asegurado es (aseguradora, cédula); una misma persona puede figurar en varios padrones. Requiere el scope members:sync y una credencial de organización tipo aseguradora — cada aseguradora solo escribe el suyo.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
required
Array of objects (InsuredMemberInput) [ 1 .. 5000 ] items

Responses

Request samples

Content type
application/json
{
  • "members": [
    ]
}

Response samples

Content type
application/json
{
  • "written": 0
}

Consulta de recepción en un solo golpe

¿La cédula está en el padrón, con la póliza activa, y tiene registro facial vigente? Es la primera llamada de la recepción. Un prestador indica la aseguradora con insurerId; una credencial de aseguradora consulta su propio padrón sin parámetro.

Authorizations:
oauth2apiKey
path Parameters
identityNumber
required
string
query Parameters
insurerId
string

Aseguradora del paciente (obligatorio para prestadores).

Responses

Response samples

Content type
application/json
{
  • "found": true,
  • "fullName": "string",
  • "policyNumber": "string",
  • "status": "active",
  • "plan": "string",
  • "enrolled": true
}

Crear una sesión de prueba de vida

En despliegues con proveedor de liveness (producción), TODO enrolamiento y verificación exige una sesión: el navegador de la recepción corre el desafío de cámara contra la sesión, y la única imagen que se compara es la de auditoría de la sesión — el cliente nunca elige qué foto se compara. Sin proveedor configurado (sandbox), responde 501 y se manda image directa.

Authorizations:
oauth2apiKey

Responses

Response samples

Content type
application/json
{
  • "sessionId": "string"
}

Registrar el rostro de un asegurado (una vez, con consentimiento)

Requiere identity:enroll. El consentimiento es obligatorio y queda registrado con su texto exacto (dato biométrico = dato sensible). Un re-enrolamiento revoca el registro anterior y ambos eventos llegan a la aseguradora por webhook. Nunca se almacena la imagen: solo la referencia opaca a la plantilla del motor biométrico. El asegurado recibe un SMS de aviso sin ningún dato clínico.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
insurerId
string

Aseguradora del paciente (prestadores).

identityNumber
required
string
consentText
required
string <= 2000 characters
image
string

Captura base64 (solo despliegues sin liveness).

livenessSessionId
string

Sesión de liveness completada (producción).

branchId
string

Responses

Request samples

Content type
application/json
{
  • "insurerId": "string",
  • "identityNumber": "string",
  • "consentText": "string",
  • "image": "string",
  • "livenessSessionId": "string",
  • "branchId": "string"
}

Response samples

Content type
application/json
{
  • "enrollmentId": "string",
  • "reEnrolled": true,
  • "createdAt": "2019-08-24T14:15:22Z"
}

Verificar la identidad del asegurado en recepción

El corazón del producto. Requiere identity:verify. En verde devuelve el código de autorización (EMD-XXXX-XX) que el prestador adjunta al claim, con su vencimiento según la política de la aseguradora. En rojo informa el motivo y los reintentos de cámara restantes; agotados, sugiere el camino de excepción (la atención nunca se bloquea). Todo intento queda en el log inmutable y se mide como transacción facturable atribuida a la aseguradora.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
insurerId
string
identityNumber
required
string
image
string

Captura base64 (solo despliegues sin liveness).

livenessSessionId
string
branchId
string

Responses

Request samples

Content type
application/json
{
  • "insurerId": "string",
  • "identityNumber": "string",
  • "image": "string",
  • "livenessSessionId": "string",
  • "branchId": "string"
}

Response samples

Content type
application/json
{
  • "result": "no_match",
  • "message": "string",
  • "attemptsLeft": 0,
  • "suggestException": true
}

Log de verificaciones (solo la aseguradora)

El registro inmutable, paginado y filtrable — la misma lectura que alimenta la consola web de la aseguradora. Requiere identity:read.

Authorizations:
oauth2apiKey
query Parameters
result
string
Enum: "verified" "no_match" "liveness_failed" "exception"
from
string <date-time>
to
string <date-time>
limit
integer
Default: 50
offset
integer
Default: 0

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Validar un código de autorización (el cruce del claim)

La aseguradora valida el código que el prestador adjuntó al claim: existe, es suyo y está dentro de su vigencia. Un claim sin código válido va a revisión. Requiere identity:read.

Authorizations:
oauth2apiKey
path Parameters
authorizationCode
required
string

Responses

Response samples

Content type
application/json
{
  • "valid": false,
  • "reason": "not_found"
}

Registrar una excepción tipificada (la atención nunca se bloquea)

Cuando la verificación no es posible (sin registro, urgencia, imposibilidad física, menor, sin conectividad), la recepción registra la excepción y la atención continúa. La aseguradora la ve en tiempo real y decide el pago; la tasa de excepciones por prestador es su detector antifraude.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
insurerId
string
identityNumber
required
string
reason
required
string
Enum: "not_enrolled" "urgency" "physical_impossibility" "minor" "no_connectivity" "other"
note
string <= 1000 characters
branchId
string

Responses

Request samples

Content type
application/json
{
  • "insurerId": "string",
  • "identityNumber": "string",
  • "reason": "not_enrolled",
  • "note": "string",
  • "branchId": "string"
}

Response samples

Content type
application/json
{
  • "attemptId": "string"
}

Actividad por prestador (el ranking antifraude)

Verificadas, fallos y excepciones por prestador en el periodo (por defecto, últimos 30 días). El prestador que esquiva la cámara se destaca solo. Requiere identity:read; cada aseguradora ve solo su actividad.

Authorizations:
oauth2apiKey
query Parameters
from
string <date-time>
to
string <date-time>

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "from": "2019-08-24T14:15:22Z",
  • "to": "2019-08-24T14:15:22Z"
}

Claims

Liquidación viva: el claim nace presentado desde la verificación, la aseguradora lo adjudica claim por claim con SLA, gana firmeza y se liquida en cortes. La planilla mensual deja de existir.

Publicar el nomenclador (solo la aseguradora)

Alta/actualización masiva de las prestaciones cubiertas, con arancel y copago. Requiere claims:manage. Un ítem con isActive: false deja de aceptar claims sin borrar su historia.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
required
Array of objects (FeeScheduleItemInput) [ 1 .. 2000 ] items

Responses

Request samples

Content type
application/json
{
  • "items": [
    ]
}

Response samples

Content type
application/json
{
  • "written": 0
}

Nomenclador vigente de una aseguradora

El prestador lo lee para registrar la prestación en un toque y saber el copago exacto a cobrar en ventanilla. Requiere claims:submit (o claims:manage para la propia aseguradora).

Authorizations:
oauth2apiKey
query Parameters
insurerId
string

Aseguradora (obligatorio para prestadores).

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Presentar un claim (nace de la verificación)

Requiere claims:submit. El claim referencia exactamente una verificación: el código de autorización verde (authorizationCode) o el intento de excepción (exceptionAttemptId) — nunca ambos. Reglas del dominio: la prestación debe estar en el nomenclador vigente, el código solo lo presenta el prestador que operó la verificación, y un intento respalda a lo sumo un claim (409 al duplicar).

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
insurerId
required
string
serviceCode
required
string
practitionerLicense
string <= 50 characters

Matrícula del médico tratante. La matrícula es la identidad profesional de la red (como la cédula lo es del paciente): cada claim llega con ella — explícita, por practitionerRef, o atada a la credencial; sin ninguna de las tres, 400. Vuelve en claim.approved/claim.objected para rutear el veredicto a la cuenta del médico en tu sistema.

practitionerRef
string <= 120 characters

Id del médico EN TU SISTEMA, resuelto por el directorio de prescriptores (POST /practitioners/sync).

authorizationCode
string
exceptionAttemptId
string

Responses

Request samples

Content type
application/json
{
  • "insurerId": "string",
  • "serviceCode": "string",
  • "practitionerLicense": "string",
  • "practitionerRef": "string",
  • "authorizationCode": "EMD-7K4P-2X",
  • "exceptionAttemptId": "ver_1a2b3c4d5e"
}

Response samples

Content type
application/json
{
  • "id": "clm_1a2b3c4d5e",
  • "insurerId": "string",
  • "providerOrgId": "string",
  • "practitionerLicense": "string",
  • "identityNumber": "string",
  • "policyNumber": "string",
  • "serviceCode": "string",
  • "serviceName": "string",
  • "amountCents": 0,
  • "copayCents": 0,
  • "currency": "string",
  • "authorizationCode": "string",
  • "verificationResult": "verified",
  • "status": "submitted",
  • "objectionReason": "string",
  • "submittedAt": "2019-08-24T14:15:22Z",
  • "adjudicatedAt": "2019-08-24T14:15:22Z",
  • "settlementId": "string",
  • "settledAt": "2019-08-24T14:15:22Z"
}

Mis claims (cada lado ve solo lo suyo)

El prestador ve los claims que presentó; la aseguradora, los presentados contra ella. Filtrable por estado.

Authorizations:
oauth2apiKey
query Parameters
status
string
Enum: "submitted" "approved" "objected" "firm" "settled"
limit
integer
Default: 50
offset
integer
Default: 0

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

La cuenta viva del prestador

Totales por estado (presentado, aprobado, objetado, firme, liquidado): lo que reemplaza a la planilla mensual. Requiere claims:submit.

Authorizations:
oauth2apiKey

Responses

Response samples

Content type
application/json
{
  • "submitted": {
    },
  • "approved": {
    },
  • "objected": {
    },
  • "firm": {
    },
  • "settled": {
    },
  • "currency": "string"
}

Adjudicar un claim (aprueba u objeta, con motivo)

La aseguradora decide claim por claim dentro del SLA del convenio. La objeción lleva su motivo y le llega al prestador por webhook al instante — no 60 días después. Requiere claims:manage.

Authorizations:
oauth2apiKey
path Parameters
claimId
required
string
Request Body schema: application/json
required
decision
required
string
Enum: "approve" "object"
objectionReason
string

Obligatorio al objetar.

Responses

Request samples

Content type
application/json
{
  • "decision": "approve",
  • "objectionReason": "string"
}

Response samples

Content type
application/json
{
  • "id": "clm_1a2b3c4d5e",
  • "insurerId": "string",
  • "providerOrgId": "string",
  • "practitionerLicense": "string",
  • "identityNumber": "string",
  • "policyNumber": "string",
  • "serviceCode": "string",
  • "serviceName": "string",
  • "amountCents": 0,
  • "copayCents": 0,
  • "currency": "string",
  • "authorizationCode": "string",
  • "verificationResult": "verified",
  • "status": "submitted",
  • "objectionReason": "string",
  • "submittedAt": "2019-08-24T14:15:22Z",
  • "adjudicatedAt": "2019-08-24T14:15:22Z",
  • "settlementId": "string",
  • "settledAt": "2019-08-24T14:15:22Z"
}

Corte de liquidación (liquida todos los claims firmes)

Marca liquidados todos los claims firmes y devuelve las líneas por prestador: a quién transferir cuánto. El corte es atómico — dos cortes concurrentes no liquidan dos veces el mismo claim. Cada prestador recibe por webhook SOLO su parte. Requiere claims:manage.

Authorizations:
oauth2apiKey

Responses

Response samples

Content type
application/json
{
  • "settlementId": "string",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "claimCount": 0,
  • "totalCents": 0,
  • "currency": "string",
  • "lines": [
    ]
}

Cortes anteriores de la aseguradora

Authorizations:
oauth2apiKey

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Financiamiento

Anticipo del banco socio, SIEMPRE opcional: el prestador que lo activa cede sus claims firmes y cobra hoy con un descuento explícito; el que no, cobra por corte sin costo. eMedic es el registro único de cesiones y el árbitro de la instrucción de dispersión — la plata nunca pasa por la plataforma.

Mi preferencia de anticipo

Requiere claims:submit. off es el default — a nadie se le impone.

Authorizations:
oauth2apiKey

Responses

Response samples

Content type
application/json
{
  • "mode": "off",
  • "feeBps": 0
}

Activar o desactivar el anticipo (opt-in)

off = cobro por corte, sin costo. manual = elijo qué claims anticipar. auto = todo claim firme se cede solo tras el barrido de firmeza. Reversible en cualquier momento.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
mode
required
string
Enum: "off" "manual" "auto"

Responses

Request samples

Content type
application/json
{
  • "mode": "off"
}

Response samples

Content type
application/json
{
  • "mode": "off",
  • "feeBps": 0
}

Claims firmes anticipables, con el costo explícito

Cada línea trae monto, descuento y neto a recibir hoy — el costo del anticipo jamás se oculta. Requiere claims:submit.

Authorizations:
oauth2apiKey

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "feeBps": 0
}

Ceder un claim firme al banco (cobrar hoy)

Reglas del registro único: solo un claim FIRME propio y sin cesión previa (409 al duplicar). La cesión avisa al banco (con el paquete de evidencia) y a la aseguradora (ese claim se paga al banco en el corte).

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
claimId
required
string

Responses

Request samples

Content type
application/json
{
  • "claimId": "string"
}

Response samples

Content type
application/json
{
  • "id": "ces_1a2b3c4d5e",
  • "claimId": "string",
  • "insurerId": "string",
  • "providerOrgId": "string",
  • "amountCents": 0,
  • "feeCents": 0,
  • "netCents": 0,
  • "currency": "string",
  • "status": "created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "paidAt": "2019-08-24T14:15:22Z"
}

Cesiones (el banco las suyas; el prestador las propias)

Authorizations:
oauth2apiKey
query Parameters
status
string
Enum: "created" "paid"
limit
integer
Default: 50
offset
integer
Default: 0

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

El banco confirma la transferencia del anticipo

Atómico: una cesión se paga UNA vez y solo por su banco. El prestador recibe advance.paid por webhook. Requiere financing:manage.

Authorizations:
oauth2apiKey
path Parameters
cessionId
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "ces_1a2b3c4d5e",
  • "claimId": "string",
  • "insurerId": "string",
  • "providerOrgId": "string",
  • "amountCents": 0,
  • "feeCents": 0,
  • "netCents": 0,
  • "currency": "string",
  • "status": "created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "paidAt": "2019-08-24T14:15:22Z"
}

Instrucción de dispersión de un corte

La pieza autoritativa que el banco recaudador ejecuta: a quién transferir cuánto — lo cedido al banco, el resto a cada prestador. La leen el banco (financing:manage) y la aseguradora (claims:manage).

Authorizations:
oauth2apiKey
path Parameters
settlementId
required
string

Responses

Response samples

Content type
application/json
{
  • "settlementId": "string",
  • "lines": [
    ]
}

Órdenes

Órdenes de estudios con visación instantánea por ítem: el médico emite contra el catálogo de la plataforma, el motor de reglas del convenio decide cada estudio en un segundo (autorizado, rechazado con motivo, o a la cola del auditor), el laboratorio la realiza una sola vez y el resultado vuelve al médico y al paciente en tiempo real. El laboratorio nunca ve el diagnóstico ni las notas del médico.

Visación de un ítem decidida (dirigido al emisor) Webhook

La familia de órdenes, toda dirigida y con la misma entrega firmada:

  • order.issued y order.item.review → a la aseguradora (lo emitido contra ella y lo que espera a su auditor).
  • order.item.authorized / order.item.rejected (con motivo), order.fulfilled y result.available → al emisor, al instante. Ningún evento lleva el contenido clínico del resultado: avisan que está disponible y se lee por la API con la credencial propia.
Authorizations:
oauth2apiKey
Request Body schema: application/json
id
string
type
string
createdAt
string <date-time>
object

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "type": "order.item.authorized",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

Resultado disponible (dirigido al emisor, en tiempo real) Webhook

El laboratorio cargó el resultado: el médico tratante se entera al instante y el paciente lo ve en su app a la par (y recibe un aviso SMS sin datos clínicos si tiene cuenta). El evento solo referencia (orderId, itemId, studyCode, abnormal, y — si la orden los trajo — practitionerLicense y externalReference para rutear a la bandeja del médico en tu sistema) — el contenido clínico se lee por GET /orders con la credencial del emisor. La marca abnormal permite priorizar sin esperar la lectura.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Catálogo de estudios de la plataforma

El catálogo único contra el que se emite toda orden: código, nombre, categoría, tipo de muestra y prerrequisitos legibles para el paciente ("Ayuno de 8 horas"). Cualquier credencial con un scope de órdenes (orders:submit, orders:manage u orders:fulfill) puede leerlo.

Authorizations:
oauth2apiKey
query Parameters
q
string >= 2 characters

Búsqueda por texto (sin distinción de tildes).

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Publicar las reglas de visación (solo la aseguradora)

Alta/actualización masiva de las reglas del convenio por código de estudio: cubierto o no, si requiere auditoría médica y el tope anual por asegurado. Con estas reglas el motor decide la mayoría de las órdenes en un segundo. Requiere orders:manage y credencial de aseguradora.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
required
Array of objects (CoverageRuleInput) [ 1 .. 2000 ] items

Responses

Request samples

Content type
application/json
{
  • "rules": [
    ]
}

Response samples

Content type
application/json
{
  • "written": 0
}

Reglas de visación vigentes de una aseguradora

El emisor las lee para anticipar el veredicto antes de emitir (orders:submit, con insurerId); la aseguradora lee las suyas (orders:manage).

Authorizations:
oauth2apiKey
query Parameters
insurerId
string

Aseguradora (obligatorio para emisores).

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Emitir una orden con visación instantánea por ítem

Requiere orders:submit. El motor decide CADA estudio en el momento con las reglas del convenio: authorized en un segundo, rejected con motivo claro, o pending_review en la cola del auditor. Un estudio no cubierto no bloquea al resto de la orden. La respuesta ya trae el veredicto de cada ítem — eso reemplaza a la foto de la orden por WhatsApp y a los días de espera.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
insurerId
required
string
patientIdentityNumber
required
string

Cédula del paciente.

patientFullName
required
string
studyCodes
required
Array of strings [ 1 .. 20 ] items
Array of objects <= 10 items

CIE-11 del emisor. Lo ven el paciente, el emisor y la aseguradora — el laboratorio JAMÁS.

notes
string <= 2000 characters

Notas del médico. Nunca llegan al laboratorio.

practitionerLicense
string <= 50 characters

Matrícula del prescriptor. La matrícula es la identidad profesional de la red: cada acto llega con ella — mandala explícita, o mandá practitionerRef, o pedí una credencial con matrícula atada; sin ninguna de las tres, 400. Vuelve en las respuestas del emisor y en los webhooks order.item.authorized/rejected, order.fulfilled y result.available, para rutear el resultado a la bandeja del médico correcto en tu sistema.

practitionerRef
string <= 120 characters

Id del médico EN TU SISTEMA (legajo, id de usuario), resuelto a matrícula por el directorio de prescriptores (POST /practitioners/sync). Cero cambios en tu HIS.

externalReference
string <= 120 characters

Id de la orden EN TU SISTEMA (texto libre, patrón placer-number). Va y vuelve intacto en respuestas y webhooks del emisor; ninguna otra audiencia lo ve.

Responses

Request samples

Content type
application/json
{
  • "insurerId": "string",
  • "patientIdentityNumber": "string",
  • "patientFullName": "string",
  • "studyCodes": [
    ],
  • "diagnoses": [
    ],
  • "notes": "string",
  • "practitionerLicense": "string",
  • "practitionerRef": "string",
  • "externalReference": "string"
}

Response samples

Content type
application/json
{
  • "id": "ord_1a2b3c4d5e6f7a8b9c0d",
  • "insurerId": "string",
  • "issuerOrgId": "string",
  • "practitionerLicense": "string",
  • "externalReference": "string",
  • "patientIdentityNumber": "string",
  • "patientFullName": "string",
  • "issuedAt": "2019-08-24T14:15:22Z",
  • "expiresAt": "2019-08-24T14:15:22Z",
  • "items": [
    ],
  • "diagnoses": [
    ],
  • "notes": "string"
}

Mis órdenes (cada lado ve solo lo suyo)

El emisor ve las órdenes que emitió, con resultados; la aseguradora, las emitidas contra ella. Filtrable por estado de ítem — la aseguradora usa itemStatus=pending_review como su cola de auditoría.

Authorizations:
oauth2apiKey
query Parameters
itemStatus
string
Enum: "pending_review" "authorized" "rejected" "fulfilled"
limit
integer
Default: 30
offset
integer
Default: 0

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Órdenes vigentes de un paciente (mostrador del laboratorio)

Requiere orders:fulfill. El paciente llega solo con su cédula: el laboratorio ve sus órdenes vigentes con ítems autorizados y los prerrequisitos de cada estudio. La vista es la audiencia lab: SIN diagnósticos, SIN notas del médico y sin resultados de otros.

Authorizations:
oauth2apiKey
path Parameters
identityNumber
required
string

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

El auditor decide un ítem pendiente (solo la aseguradora)

Requiere orders:manage. Solo aplica a ítems pending_review; el emisor recibe order.item.authorized o order.item.rejected al instante, y el paciente lo ve reflejado en su app. Un rechazo lleva su motivo, siempre.

Authorizations:
oauth2apiKey
path Parameters
orderId
required
string
itemId
required
string
Request Body schema: application/json
required
decision
required
string
Enum: "authorize" "reject"
rejectReason
string

Obligatorio al rechazar.

Responses

Request samples

Content type
application/json
{
  • "decision": "authorize",
  • "rejectReason": "string"
}

Response samples

Content type
application/json
{
  • "id": "ord_1a2b3c4d5e6f7a8b9c0d",
  • "insurerId": "string",
  • "issuerOrgId": "string",
  • "practitionerLicense": "string",
  • "externalReference": "string",
  • "patientIdentityNumber": "string",
  • "patientFullName": "string",
  • "issuedAt": "2019-08-24T14:15:22Z",
  • "expiresAt": "2019-08-24T14:15:22Z",
  • "items": [
    ],
  • "diagnoses": [
    ],
  • "notes": "string"
}

El laboratorio realiza un ítem autorizado (un solo uso)

Requiere orders:fulfill. Single-use atómico: el primer laboratorio que lo marca se lo queda; un segundo intento — propio o de otro laboratorio — recibe 409. Una orden vencida no se realiza (ORDER_EXPIRED).

Authorizations:
oauth2apiKey
path Parameters
orderId
required
string
itemId
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "ord_1a2b3c4d5e6f7a8b9c0d",
  • "insurerId": "string",
  • "issuerOrgId": "string",
  • "practitionerLicense": "string",
  • "externalReference": "string",
  • "patientIdentityNumber": "string",
  • "patientFullName": "string",
  • "issuedAt": "2019-08-24T14:15:22Z",
  • "expiresAt": "2019-08-24T14:15:22Z",
  • "items": [
    ],
  • "diagnoses": [
    ],
  • "notes": "string"
}

Cargar el resultado de un ítem realizado

Requiere orders:fulfill y solo lo acepta el laboratorio que realizó el ítem. El resultado viaja en tiempo real y a la par: el emisor recibe result.available y el paciente lo ve en su app — nadie más.

Authorizations:
oauth2apiKey
path Parameters
orderId
required
string
itemId
required
string
Request Body schema: application/json
required
resultText
string <= 10000 characters

Resumen u observaciones en texto (opcional).

Array of objects (ResultValueInput) <= 100 items

Valores estructurados del informe. outOfRange omitido se deriva del rango cuando el valor es numérico. El rango es SIEMPRE el del informe del laboratorio.

resultPdfBase64
string

El informe ORIGINAL en PDF (base64, ~5 MB máx). El dato estructurado convive con el documento, jamás lo reemplaza: emisor y paciente lo abren con su botón.

resultAttachmentRef
string

Referencia externa al documento (alternativa al PDF).

resultAbnormal
boolean

Fuera de rango según el laboratorio: el médico tratante lo ve primero en su bandeja y el evento lo lleva como abnormal. Omitido, con resultValues deciden los rangos.

Responses

Request samples

Content type
application/json
{
  • "resultText": "string",
  • "resultValues": [
    ],
  • "resultPdfBase64": "string",
  • "resultAttachmentRef": "string",
  • "resultAbnormal": true
}

Response samples

Content type
application/json
{
  • "error": {
    }
}

Analitos típicos de un estudio (pre-llenado del informe)

Sugerencias de analitos con unidad y rango de referencia GENERALES, para pre-llenar el LIS o el mostrador. El rango autoritativo es siempre el del informe del laboratorio que procesó la muestra. Cualquier scope de órdenes puede leerlas.

Authorizations:
oauth2apiKey
path Parameters
studyCode
required
string

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

El informe original del ítem (PDF)

El botón "Ver informe original": el dato estructurado convive con el documento, jamás lo reemplaza. Lo lee el emisor de la orden (orders:submit) o la aseguradora del convenio (orders:manage); una organización ajena recibe 404.

Authorizations:
oauth2apiKey
path Parameters
orderId
required
string
itemId
required
string

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Agenda

Agenda por prescriptor y turnos: la clínica define franjas, duración y colchón; la disponibilidad se calcula sola; la reserva es atómica (dos pedidos por el mismo hueco jamás ganan los dos) y cada cambio de estado sale como webhook dirigido a la clínica dueña. El motivo de consulta nunca viaja en los eventos.

Turno reservado (y la familia de la agenda) Webhook

Representa a toda la familia de eventos de agendamiento — appointment.booked, appointment.confirmed, appointment.cancelled, appointment.completed y appointment.no_show — todos con el mismo payload y SIEMPRE dirigidos a la clínica dueña de la agenda: así su sistema (HIS, calendario, recordatorios) se sincroniza sin consultar. El data lleva solo appointmentId, practitionerLicense, patientIdentityNumber, startAt, endAt y status — el motivo de consulta y las notas jamás viajan por webhook.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Configurar la agenda de un prescriptor

Franjas de atención en hora local de la agenda (zona IANA), duración del turno, colchón entre turnos y tope diario. La disponibilidad se calcula a partir de esto: no hay calendarios que sincronizar. Solo organizaciones que atienden pacientes (clínicas, laboratorios). Requiere scheduling:manage.

Authorizations:
oauth2apiKey
path Parameters
license
required
string

Matrícula del prescriptor (la misma clave que órdenes y claims).

Request Body schema: application/json
required
timezone
required
string

Zona horaria IANA de las franjas.

slotMinutes
required
integer [ 5 .. 240 ]
bufferMinutes
required
integer [ 0 .. 120 ]
maxPerDay
integer or null [ 1 .. 200 ]
required
Array of objects (WorkingDay)

Responses

Request samples

Content type
application/json
{
  • "timezone": "America/Asuncion",
  • "slotMinutes": 5,
  • "bufferMinutes": 120,
  • "maxPerDay": 1,
  • "workingDays": [
    ]
}

Response samples

Content type
application/json
{
  • "timezone": "America/Asuncion",
  • "slotMinutes": 5,
  • "bufferMinutes": 120,
  • "maxPerDay": 1,
  • "workingDays": [
    ],
  • "practitionerLicense": "string"
}

Consultar la agenda configurada

Requiere scheduling:read o scheduling:manage.

Authorizations:
oauth2apiKey
path Parameters
license
required
string

Matrícula del prescriptor (la misma clave que órdenes y claims).

Responses

Response samples

Content type
application/json
{
  • "timezone": "America/Asuncion",
  • "slotMinutes": 5,
  • "bufferMinutes": 120,
  • "maxPerDay": 1,
  • "workingDays": [
    ],
  • "practitionerLicense": "string"
}

Huecos libres de un día

Los huecos del día según la agenda, descontando los turnos vivos, el colchón, el tope diario y lo ya pasado. Los horarios vuelven como instantes UTC. Requiere scheduling:read o scheduling:manage.

Authorizations:
oauth2apiKey
path Parameters
license
required
string

Matrícula del prescriptor (la misma clave que órdenes y claims).

query Parameters
date
required
string <date>

Día a consultar (YYYY-MM-DD, calendario de la agenda).

Responses

Response samples

Content type
application/json
{
  • "date": "2019-08-24",
  • "timezone": "string",
  • "slotMinutes": 0,
  • "practitionerLicense": "string",
  • "slots": [
    ]
}

Reservar un turno

Reserva atómica: dos pedidos por el mismo hueco jamás ganan los dos — el perdedor recibe 409 CONFLICT con la franja ocupada (nunca con los datos del otro paciente). Sin endAt, el turno dura slotMinutes de la agenda (o 30 minutos). El evento appointment.booked sale dirigido a tu organización. Requiere scheduling:manage.

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
practitionerLicense
required
string
practitionerName
string
required
object (AppointmentPatient)
startAt
required
string <date-time>

Instante UTC (ISO 8601 con zona).

endAt
string <date-time>

Opcional; sin esto dura slotMinutes de la agenda (o 30').

reason
string <= 2000 characters

Motivo de consulta; jamás sale de tu organización.

notes
string <= 2000 characters

Responses

Request samples

Content type
application/json
{
  • "practitionerLicense": "string",
  • "practitionerName": "string",
  • "patient": {
    },
  • "startAt": "2019-08-24T14:15:22Z",
  • "endAt": "2019-08-24T14:15:22Z",
  • "reason": "string",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "id": "apt_1f2e3d4c5b6a79881726",
  • "practitionerLicense": "string",
  • "practitionerName": "string",
  • "patient": {
    },
  • "startAt": "2019-08-24T14:15:22Z",
  • "endAt": "2019-08-24T14:15:22Z",
  • "status": "scheduled",
  • "reason": "string",
  • "notes": "string",
  • "cancelReason": "string",
  • "createdAt": "2019-08-24T14:15:22Z"
}

Turnos propios

Solo los turnos de tu organización, ordenados por inicio. Requiere scheduling:read o scheduling:manage.

Authorizations:
oauth2apiKey
query Parameters
practitionerLicense
string
from
string <date-time>
to
string <date-time>
status
string (AppointmentStatus)
Enum: "scheduled" "confirmed" "completed" "cancelled" "no_show"
limit
integer [ 1 .. 100 ]
Default: 20
offset
integer >= 0
Default: 0

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Detalle de un turno propio

Requiere scheduling:read o scheduling:manage.

Authorizations:
oauth2apiKey
path Parameters
appointmentId
required
string

ID del turno (apt_...).

Responses

Response samples

Content type
application/json
{
  • "id": "apt_1f2e3d4c5b6a79881726",
  • "practitionerLicense": "string",
  • "practitionerName": "string",
  • "patient": {
    },
  • "startAt": "2019-08-24T14:15:22Z",
  • "endAt": "2019-08-24T14:15:22Z",
  • "status": "scheduled",
  • "reason": "string",
  • "notes": "string",
  • "cancelReason": "string",
  • "createdAt": "2019-08-24T14:15:22Z"
}

Confirmar un turno

scheduled → confirmed; publica appointment.confirmed. Requiere scheduling:manage.

Authorizations:
oauth2apiKey
path Parameters
appointmentId
required
string

ID del turno (apt_...).

Responses

Response samples

Content type
application/json
{
  • "id": "apt_1f2e3d4c5b6a79881726",
  • "practitionerLicense": "string",
  • "practitionerName": "string",
  • "patient": {
    },
  • "startAt": "2019-08-24T14:15:22Z",
  • "endAt": "2019-08-24T14:15:22Z",
  • "status": "scheduled",
  • "reason": "string",
  • "notes": "string",
  • "cancelReason": "string",
  • "createdAt": "2019-08-24T14:15:22Z"
}

Cancelar un turno

El hueco vuelve a estar libre al instante; publica appointment.cancelled. Un turno cancelado es terminal. Requiere scheduling:manage.

Authorizations:
oauth2apiKey
path Parameters
appointmentId
required
string

ID del turno (apt_...).

Request Body schema: application/json
optional
reason
string <= 500 characters

Responses

Request samples

Content type
application/json
{
  • "reason": "string"
}

Response samples

Content type
application/json
{
  • "id": "apt_1f2e3d4c5b6a79881726",
  • "practitionerLicense": "string",
  • "practitionerName": "string",
  • "patient": {
    },
  • "startAt": "2019-08-24T14:15:22Z",
  • "endAt": "2019-08-24T14:15:22Z",
  • "status": "scheduled",
  • "reason": "string",
  • "notes": "string",
  • "cancelReason": "string",
  • "createdAt": "2019-08-24T14:15:22Z"
}

Marcar un turno como atendido

Publica appointment.completed. Requiere scheduling:manage.

Authorizations:
oauth2apiKey
path Parameters
appointmentId
required
string

ID del turno (apt_...).

Responses

Response samples

Content type
application/json
{
  • "id": "apt_1f2e3d4c5b6a79881726",
  • "practitionerLicense": "string",
  • "practitionerName": "string",
  • "patient": {
    },
  • "startAt": "2019-08-24T14:15:22Z",
  • "endAt": "2019-08-24T14:15:22Z",
  • "status": "scheduled",
  • "reason": "string",
  • "notes": "string",
  • "cancelReason": "string",
  • "createdAt": "2019-08-24T14:15:22Z"
}

Marcar que el paciente no vino

Publica appointment.no_show. Requiere scheduling:manage.

Authorizations:
oauth2apiKey
path Parameters
appointmentId
required
string

ID del turno (apt_...).

Responses

Response samples

Content type
application/json
{
  • "id": "apt_1f2e3d4c5b6a79881726",
  • "practitionerLicense": "string",
  • "practitionerName": "string",
  • "patient": {
    },
  • "startAt": "2019-08-24T14:15:22Z",
  • "endAt": "2019-08-24T14:15:22Z",
  • "status": "scheduled",
  • "reason": "string",
  • "notes": "string",
  • "cancelReason": "string",
  • "createdAt": "2019-08-24T14:15:22Z"
}

Transcripción

Transcripción médica: el médico dicta y la plataforma devuelve la transcripción fiel, una nota clínica estructurada (con diagnósticos codificables a CIE-11) y, si se dictaron medicamentos, un borrador de receta que el médico confirma y firma. Asíncrono, con webhook sin contenido clínico. Nada se inventa: lo dudoso queda declarado en issues.

Transcripción lista (o fallida) Webhook

Representa a transcription.completed y transcription.failed, SIEMPRE dirigidos a la clínica dueña y SIN contenido clínico: el data lleva solo transcriptionId, status, durationSeconds y — si se mandaron — practitionerLicense y externalReference para rutear a la bandeja del médico en tu sistema. La nota se lee por GET /transcriptions/{id} con tu credencial.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Mandar un audio a transcribir

El médico dicta (o se graba la consulta) y la plataforma devuelve la transcripción fiel más una nota clínica estructurada y, si se dictaron medicamentos, un borrador de receta. El proceso es asíncrono: esto devuelve 202 con estado pending; el resultado se consulta por id o llega el webhook transcription.completed (sin contenido clínico). El borrador jamás se emite solo: la receta la confirma y firma el médico por los canales de siempre. Audio hasta 20 MB en base64. Requiere transcription:manage (solo clínicas).

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
audioBase64
required
string

El audio en base64 (hasta ~20 MB de audio).

contentType
required
string
Enum: "audio/mpeg" "audio/mp3" "audio/mp4" "audio/x-m4a" "audio/wav" "audio/x-wav" "audio/webm" "audio/ogg" "audio/flac"

Tipo del audio.

language
string

Idioma del dictado (default es).

practitionerLicense
string

Matrícula del médico que dicta (rutea la nota en tu sistema).

patientIdentityNumber
string

Cédula del paciente, para ligar la nota a su historia.

externalReference
string <= 200 characters

Referencia de la consulta en tu sistema; vuelve en el webhook.

Responses

Request samples

Content type
application/json
{
  • "audioBase64": "string",
  • "contentType": "audio/mpeg",
  • "language": "es",
  • "practitionerLicense": "string",
  • "patientIdentityNumber": "string",
  • "externalReference": "string"
}

Response samples

Content type
application/json
{
  • "id": "trx_9f8e7d6c5b4a32101234",
  • "status": "pending",
  • "language": "string",
  • "audioContentType": "string",
  • "audioSizeBytes": 0,
  • "durationSeconds": 0,
  • "practitionerLicense": "string",
  • "patientIdentityNumber": "string",
  • "externalReference": "string",
  • "transcript": "string",
  • "note": {
    },
  • "prescriptionDraft": {
    },
  • "issues": [
    ],
  • "error": "string",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "completedAt": "2019-08-24T14:15:22Z"
}

Transcripciones propias

Solo las de tu organización. Requiere transcription:manage.

Authorizations:
oauth2apiKey
query Parameters
status
string
Enum: "pending" "processing" "completed" "failed"
practitionerLicense
string
limit
integer [ 1 .. 100 ]
Default: 20
offset
integer >= 0
Default: 0

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Resultado de una transcripción

Transcripción fiel, nota clínica, borrador de receta y dudas declaradas (issues). Requiere transcription:manage.

Authorizations:
oauth2apiKey
path Parameters
transcriptionId
required
string

ID de la transcripción (trx_...).

Responses

Response samples

Content type
application/json
{
  • "id": "trx_9f8e7d6c5b4a32101234",
  • "status": "pending",
  • "language": "string",
  • "audioContentType": "string",
  • "audioSizeBytes": 0,
  • "durationSeconds": 0,
  • "practitionerLicense": "string",
  • "patientIdentityNumber": "string",
  • "externalReference": "string",
  • "transcript": "string",
  • "note": {
    },
  • "prescriptionDraft": {
    },
  • "issues": [
    ],
  • "error": "string",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "completedAt": "2019-08-24T14:15:22Z"
}

Audio original

El audio tal como se mandó, para auditoría de la clínica dueña. Requiere transcription:manage.

Authorizations:
oauth2apiKey
path Parameters
transcriptionId
required
string

ID de la transcripción (trx_...).

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Imágenes

IA de imágenes (radiografías, ECG y más) como apoyo a la decisión clínica: informe preliminar con hallazgos, impresión, urgencia sugerida conservadora y limitaciones declaradas. Todo informe lleva un disclaimer fijo — no es diagnóstico, el médico que mira la imagen decide — y ninguna acción clínica se dispara sola.

Análisis de imagen listo (o fallido) Webhook

Representa a imaging.completed e imaging.failed, SIEMPRE dirigidos a la organización dueña y SIN contenido clínico: el data lleva analysisId, status, modality, la urgency sugerida (para priorizar la bandeja del médico sin exponer hallazgos) y — si se mandaron — practitionerLicense y externalReference. El informe se lee por GET /imaging/analyses/{id} con tu credencial.

Authorizations:
oauth2apiKey
Request Body schema: application/json
id
required
string

ID del evento (estable entre reintentos).

type
required
string (WebhookEventType)
Enum: "prescription.created" "prescription.dispensed" "prescription.fully_dispensed" "prescription.cancelled" "prescription.expired" "patient.contact_updated" "identity.enrollment.completed" "identity.enrollment.revoked" "identity.verification.completed" "identity.exception.recorded" "claim.submitted" "claim.approved" "claim.objected" "claim.firm" "claim.ceded" "advance.paid" "settlement.created" "order.issued" "order.item.authorized" "order.item.rejected" "order.item.review" "order.fulfilled" "result.available" "appointment.booked" "appointment.confirmed" "appointment.cancelled" "appointment.completed" "appointment.no_show" "transcription.completed" "transcription.failed" "imaging.completed" "imaging.failed"
createdAt
required
string <date-time>
data
required
object

Para prescription.*: la receta (Prescription); para prescription.dispensed incluye además la dispensación (dispensation).

Responses

Request samples

Content type
application/json
{
  • "id": "evt_01J8ZF9X1Q",
  • "type": "prescription.created",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "data": { }
}

Mandar un estudio a analizar

Radiografías, ECG y otras imágenes (PNG/JPEG/WebP/GIF, hasta 5 MB) vuelven como un informe preliminar de apoyo a la decisión clínica: hallazgos, impresión preliminar, urgencia sugerida (conservadora) y limitaciones declaradas. Todo informe lleva un disclaimer fijo: no es diagnóstico — el médico que mira la imagen decide. Asíncrono: 202 pending y el webhook imaging.completed (con la urgencia para priorizar bandejas, sin ningún hallazgo). Requiere imaging:manage (clínicas y laboratorios).

Authorizations:
oauth2apiKey
Request Body schema: application/json
required
imageBase64
required
string

La imagen en base64 (hasta 5 MB).

contentType
required
string
Enum: "image/png" "image/jpeg" "image/webp" "image/gif"
modality
required
string
Enum: "xray" "ecg" "ct" "mri" "ultrasound" "other"
bodyPart
string <= 200 characters

Región anatómica (p. ej. "tórax PA").

clinicalContext
string <= 2000 characters

Contexto clínico que el médico aporta; jamás sale de tu organización.

practitionerLicense
string

Matrícula del médico (rutea el informe en tu sistema).

patientIdentityNumber
string
externalReference
string <= 200 characters

Referencia del estudio en tu sistema; vuelve en el webhook.

Responses

Request samples

Content type
application/json
{
  • "imageBase64": "string",
  • "contentType": "image/png",
  • "modality": "xray",
  • "bodyPart": "string",
  • "clinicalContext": "string",
  • "practitionerLicense": "string",
  • "patientIdentityNumber": "string",
  • "externalReference": "string"
}

Response samples

Content type
application/json
{
  • "id": "img_4a3b2c1d0e9f87651234",
  • "status": "pending",
  • "modality": "xray",
  • "bodyPart": "string",
  • "clinicalContext": "string",
  • "imageContentType": "string",
  • "imageSizeBytes": 0,
  • "practitionerLicense": "string",
  • "patientIdentityNumber": "string",
  • "externalReference": "string",
  • "report": {
    },
  • "disclaimer": "string",
  • "issues": [
    ],
  • "error": "string",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "completedAt": "2019-08-24T14:15:22Z"
}

Análisis propios

Solo los de tu organización. Requiere imaging:manage.

Authorizations:
oauth2apiKey
query Parameters
status
string
Enum: "pending" "processing" "completed" "failed"
practitionerLicense
string
limit
integer [ 1 .. 100 ]
Default: 20
offset
integer >= 0
Default: 0

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Informe de un análisis

Hallazgos, impresión preliminar, urgencia, limitaciones y el disclaimer de apoyo a la decisión. Requiere imaging:manage.

Authorizations:
oauth2apiKey
path Parameters
analysisId
required
string

ID del análisis (img_...).

Responses

Response samples

Content type
application/json
{
  • "id": "img_4a3b2c1d0e9f87651234",
  • "status": "pending",
  • "modality": "xray",
  • "bodyPart": "string",
  • "clinicalContext": "string",
  • "imageContentType": "string",
  • "imageSizeBytes": 0,
  • "practitionerLicense": "string",
  • "patientIdentityNumber": "string",
  • "externalReference": "string",
  • "report": {
    },
  • "disclaimer": "string",
  • "issues": [
    ],
  • "error": "string",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "completedAt": "2019-08-24T14:15:22Z"
}

Imagen original

La imagen tal como se mandó, para auditoría de la organización dueña. Requiere imaging:manage.

Authorizations:
oauth2apiKey
path Parameters
analysisId
required
string

ID del análisis (img_...).

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Prescriptores

Declarar el plantel de prescriptores de tu organización

La matrícula es la identidad profesional de la red. Si tu sistema no tiene un campo de matrícula, declarás tu plantel UNA vez acá — el id interno de cada médico (externalRef) y su matrícula — y desde ahí emitís órdenes y presentás claims con practitionerRef: cero cambios en tu HIS. Upsert por matrícula: re-declarar actualiza nombre y ref sin duplicar ni pisar la verificación del operador.

Authorizations:
apiKey
Request Body schema: application/json
required
required
Array of objects [ 1 .. 1000 ] items

Responses

Request samples

Content type
application/json
{
  • "practitioners": [
    ]
}

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Listar el plantel declarado de tu organización

Authorizations:
apiKey

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}