Skip to main content

API Reference — Subscriptions & Licenses

Esta sección documenta los endpoints disponibles para la gestión de providers hijos, credenciales, y consulta de licencias y suscripciones.

🔒 Todos los endpoints requieren autenticación. Consulta la sección de Autenticación para obtener tu token y usarlo en la cabecera Authorization: Bearer <token>.


Crear provider hijo

Permite al provider padre registrar un nuevo provider hijo en la plataforma.

👨🏻‍💻 QA:

POST https://api-qa.speaknosis.com/iam/v1/register/childProvider

🏥 Producción:

POST https://api-prod.speaknosis.com/iam/v1/register/childProvider

Body (application/json):

{
"name": "Clínica Hija",
"country": "Chile",
"city": "Santiago"
}
CampoTipoObligatorioDescripción
namestringNombre del establecimiento.
countrystringPaís de ubicación.
citystringCiudad de ubicación.

Respuesta exitosa (200 OK):

{
"success": true,
"code": 200,
"response": {
"providerId": 1042,
"clientId": "speaknosis-client-xxxxx",
"secret": "xxxxxxxxxxxxxxxxxxxxxxxx"
}
}

⚠️ Guardá el providerId, clientId y secret. Los necesitarás para todos los pasos siguientes.


Obtener credenciales del provider hijo

Recupera las credenciales de autenticación de un provider hijo existente.

👨🏻‍💻 QA:

GET https://api-qa.speaknosis.com/iam/v1/provider/{childProviderId}/credentials

🏥 Producción:

GET https://api-prod.speaknosis.com/iam/v1/provider/{childProviderId}/credentials
ParámetroUbicaciónTipoObligatorioDescripción
childProviderIdpathstringID del provider hijo.

Respuesta exitosa (200 OK):

{
"success": true,
"code": 200,
"response": {
"clientId": "speaknosis-client-xxxxx",
"secret": "xxxxxxxxxxxxxxxxxxxxxxxx"
}
}

Listar providers hijos

Retorna todos los providers hijos vinculados al provider padre autenticado.

👨🏻‍💻 QA:

GET https://api-qa.speaknosis.com/core/v1/provider/{providerId}/child

🏥 Producción:

GET https://api-prod.speaknosis.com/core/v1/provider/{providerId}/child
ParámetroUbicaciónTipoObligatorioDescripción
providerIdpathstringID del provider padre.
limitquerynumberNoCantidad de resultados por página. Si no se envía, retorna todos los hijos.
offsetquerynumberNoCantidad de resultados a saltar. Por defecto: 0.

Ejemplo con paginación:

GET .../child?limit=10&offset=20

Respuesta exitosa (200 OK):

{
"success": true,
"code": 200,
"response": {
"data": [
{
"id": 1042,
"name": "Clínica Hija",
"country": "Chile"
}
],
"meta": {
"total": 45,
"offset": 0,
"limit": 10
}
}
}
CampoTipoDescripción
dataarrayListado de providers hijos.
meta.totalnumberTotal de providers hijos del padre.
meta.offsetnumberOffset aplicado en la consulta.
meta.limitnumberLímite aplicado. Si no se envió limit, coincide con total (se trajo todo).

Suscripciones y Licencias

Consultar usuarios con sus licencias

Retorna el listado de doctores registrados en el provider junto con el estado de su licencia asignada.

👨🏻‍💻 QA:

GET https://api-qa.speaknosis.com/payments/v1/subscription/provider/{providerId}/user

🏥 Producción:

GET https://api-prod.speaknosis.com/payments/v1/subscription/provider/{providerId}/user
ParámetroUbicaciónTipoObligatorioDescripción
providerIdpathstringID interno del provider.
limitquerynumberNoCantidad de resultados por página. Por defecto: 10.
offsetquerynumberNoCantidad de resultados a saltar. Por defecto: 0.
searchquerystringNoFiltra por nombre o apellido del doctor (coincidencia parcial, sin distinguir mayúsculas).

Ejemplo con paginación:

GET .../user?limit=20&offset=40

Respuesta exitosa (200 OK):

{
"success": true,
"code": 200,
"response": {
"doctors": [
{
"id": "tu-id-externo-1",
"name": "Juan",
"lastname": "Pérez",
"license": {
"type": "BASIC",
"isEnabled": true,
"currentUsage": 12,
"limit": 100,
"expiresAt": "2026-06-01T00:00:00.000Z"
}
},
{
"id": "tu-id-externo-2",
"name": "María",
"lastname": "González",
"license": null
}
],
"suspension": {
"suspended": false
},
"billing": {
"mode": "STRIPE",
"managedBy": null
},
"meta": {
"total": 152,
"offset": 0,
"limit": 20
}
}
}
CampoTipoDescripción
doctors[].idstringID externo del doctor en tu sistema.
doctors[].licenseobjectLicencia asignada. null si el doctor no tiene licencia.
license.typestringTipo de licencia: BASIC, ELITE o TRIAL.
license.isEnabledbooleanSi la licencia está activa. Es false cuando el usuario llegó al límite de consultas de un plan Basic, o cuando la suscripción del provider está suspendida por falta de pago (en ese caso quedan en false todas las licencias del provider).
license.currentUsagenumberConsultas realizadas en el período actual.
license.limitnumberLímite mensual de consultas. null para plan ELITE (sin límite).
license.expiresAtstringFecha de vencimiento de la licencia.
suspension.suspendedbooleanSi el acceso del provider está cortado por falta de pago. Solo se devuelve para providers que facturan por Stripe; ver la nota de abajo.
suspension.reasonstringMotivo del corte. Presente solo cuando suspended es true; hoy el único valor es payment_failed.
billing.modestringRégimen de facturación del provider: STRIPE si contrata y paga desde el portal de Speaknosis, PARTNER_SELF si le factura su provider padre.
billing.managedBystringNombre del provider que gestiona el cobro cuando mode es PARTNER_SELF. null en el flujo Stripe.
meta.totalnumberTotal de doctores del provider, útil para calcular páginas.
meta.offsetnumberOffset aplicado en la consulta.
meta.limitnumberLímite aplicado. Si no se envió limit, coincide con total (se trajo todo).

ℹ️ suspension según el régimen de facturación. El corte por falta de pago solo existe en el flujo Stripe, así que para un provider con billing.mode = "PARTNER_SELF" el campo suspension no viene. Si tu integración lo lee, tratá su ausencia como "sin corte".

Ejemplo de la respuesta para un provider con facturación del padre (solo la parte que cambia):

{
"response": {
"doctors": [],
"billing": {
"mode": "PARTNER_SELF",
"managedBy": "PartnerX"
},
"meta": { "total": 0, "offset": 0, "limit": 20 }
}
}

Consultar licencias del provider

Permite consultar el resumen de licencias del provider, o filtrar por usuario específico.

👨🏻‍💻 QA:

GET https://api-qa.speaknosis.com/payments/v1/subscription/provider/{providerId}/license

🏥 Producción:

GET https://api-prod.speaknosis.com/payments/v1/subscription/provider/{providerId}/license
ParámetroUbicaciónTipoObligatorioDescripción
providerIdpathstringID interno del provider.
userIdquerystringNoID externo del usuario para filtrar sus licencias específicas.
typequerystringNoFiltra por plan: BASIC, ELITE o TRIAL. Devuelve el detalle de licencias, no el resumen.

Sin userId — Resumen general

Retorna el total de licencias contratadas, en uso y disponibles por plan, más información de downgrade programado si existe.

Respuesta exitosa (200 OK):

{
"success": true,
"code": 200,
"response": {
"summary": [
{
"type": "BASIC",
"total": 10,
"used": 7,
"available": 3
},
{
"type": "ELITE",
"total": 5,
"used": 5,
"available": 0
}
],
"scheduledDowngrade": {
"quantity": {
"8": 6,
"9": 3
},
"effectiveDate": "2026-07-01T00:00:00.000Z"
},
"suspension": {
"suspended": false
}
}
}

ℹ️ scheduledDowngrade es null si no hay downgrade programado. suspension.suspended indica si el acceso del provider está cortado por falta de pago, y lleva un reason (hoy solo payment_failed) cuando es true.

Providers con facturación del padre. Cuando el provider factura a través de su padre (billing.mode = "PARTNER_SELF", ver Consultar usuarios con sus licencias), el downgrade programado y el corte por falta de pago no aplican: en su lugar la respuesta trae el estado del contrato.

{
"success": true,
"code": 200,
"response": {
"summary": [
{
"type": "BASIC",
"total": 1,
"used": 0,
"available": 1
}
],
"status": "ACTIVE"
}
}
CampoTipoDescripción
statusstringEstado del contrato: ACTIVE si está vigente (incluido el período de prueba), INACTIVE si el padre lo dio de baja. Solo se devuelve en el flujo PARTNER_SELF.

En ese flujo no vienen scheduledDowngrade ni suspension. Tratá la ausencia de cada uno como "no hay downgrade programado" y "sin corte", respectivamente.

Con userId — Licencia de un usuario específico

Ejemplo:

GET .../license?userId=tu-id-externo-1

Respuesta exitosa (200 OK):

{
"success": true,
"code": 200,
"response": {
"licenses": [
{
"id": 301,
"type": "BASIC",
"limit": 100,
"currentUsage": 12,
"isEnabled": true,
"createdAt": "2026-01-15 10:00:00",
"updatedAt": "2026-05-20 08:30:00",
"lastUsedAt": "2026-05-20 08:30:00",
"expiresAt": "2026-06-01T00:00:00.000Z",
"userId": "tu-id-externo-1",
"name": "Juan",
"lastname": "Pérez"
}
],
"suspension": {
"suspended": false
}
}
}

ℹ️ Igual que en el resumen general, suspension no viene para providers con billing.mode = "PARTNER_SELF".


Webhook del partner (self-billing)

Solo para providers padre habilitados en régimen self-billing. Permite notificar a Speaknosis las altas, los cambios de cantidad y las bajas de sus centros.

👨🏻‍💻 QA:

POST https://api-qa.speaknosis.com/payments/v1/partner/webhook

🏥 Producción:

POST https://api-prod.speaknosis.com/payments/v1/partner/webhook
Evento (type)Para qué
checkout.session.completedAlta del contrato del centro
customer.subscription.updatedCambio de cantidad, actualización de datos del contrato o reactivación
customer.subscription.deletedBaja: corta el acceso sin borrar datos

El contrato completo —envelope, campos, idempotencia, códigos de respuesta y política de reintentos— está en 👉 Self-billing.

Un centro que no está configurado para self-billing responde 409.


Códigos de error comunes

CódigoDescripción
400Cuerpo o parámetros inválidos.
401Token de autenticación faltante o inválido.
403Sin permisos para acceder a este recurso.
404Recurso no encontrado (provider, usuario o licencia inexistente).
409La operación no aplica al régimen de facturación del centro (por ejemplo, contratar por Stripe un centro en self-billing, o enviar al webhook del partner un centro que no lo está).
422Cuerpo válido pero inaplicable al estado actual del centro. Reintentable.