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"
}
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
name | string | Sí | Nombre del establecimiento. |
country | string | Sí | País de ubicación. |
city | string | Sí | Ciudad de ubicación. |
Respuesta exitosa (200 OK):
{
"success": true,
"code": 200,
"response": {
"providerId": 1042,
"clientId": "speaknosis-client-xxxxx",
"secret": "xxxxxxxxxxxxxxxxxxxxxxxx"
}
}
⚠️ Guardá el
providerId,clientIdysecret. 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ámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
childProviderId | path | string | Sí | ID 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ámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
providerId | path | string | Sí | ID del provider padre. |
limit | query | number | No | Cantidad de resultados por página. Si no se envía, retorna todos los hijos. |
offset | query | number | No | Cantidad 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
}
}
}
| Campo | Tipo | Descripción |
|---|---|---|
data | array | Listado de providers hijos. |
meta.total | number | Total de providers hijos del padre. |
meta.offset | number | Offset aplicado en la consulta. |
meta.limit | number | Lí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ámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
providerId | path | string | Sí | ID interno del provider. |
limit | query | number | No | Cantidad de resultados por página. Por defecto: 10. |
offset | query | number | No | Cantidad de resultados a saltar. Por defecto: 0. |
search | query | string | No | Filtra 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
}
}
}
| Campo | Tipo | Descripción |
|---|---|---|
doctors[].id | string | ID externo del doctor en tu sistema. |
doctors[].license | object | Licencia asignada. null si el doctor no tiene licencia. |
license.type | string | Tipo de licencia: BASIC, ELITE o TRIAL. |
license.isEnabled | boolean | Si 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.currentUsage | number | Consultas realizadas en el período actual. |
license.limit | number | Límite mensual de consultas. null para plan ELITE (sin límite). |
license.expiresAt | string | Fecha de vencimiento de la licencia. |
suspension.suspended | boolean | Si 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.reason | string | Motivo del corte. Presente solo cuando suspended es true; hoy el único valor es payment_failed. |
billing.mode | string | Ré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.managedBy | string | Nombre del provider que gestiona el cobro cuando mode es PARTNER_SELF. null en el flujo Stripe. |
meta.total | number | Total de doctores del provider, útil para calcular páginas. |
meta.offset | number | Offset aplicado en la consulta. |
meta.limit | number | Límite aplicado. Si no se envió limit, coincide con total (se trajo todo). |
ℹ️
suspensionsegún el régimen de facturación. El corte por falta de pago solo existe en el flujo Stripe, así que para un provider conbilling.mode = "PARTNER_SELF"el camposuspensionno 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ámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
providerId | path | string | Sí | ID interno del provider. |
userId | query | string | No | ID externo del usuario para filtrar sus licencias específicas. |
type | query | string | No | Filtra 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
}
}
}
ℹ️
scheduledDowngradeesnullsi no hay downgrade programado.suspension.suspendedindica si el acceso del provider está cortado por falta de pago, y lleva unreason(hoy solopayment_failed) cuando estrue.
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"
}
}
| Campo | Tipo | Descripción |
|---|---|---|
status | string | Estado 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,
suspensionno viene para providers conbilling.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.completed | Alta del contrato del centro |
customer.subscription.updated | Cambio de cantidad, actualización de datos del contrato o reactivación |
customer.subscription.deleted | Baja: 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ódigo | Descripción |
|---|---|
400 | Cuerpo o parámetros inválidos. |
401 | Token de autenticación faltante o inválido. |
403 | Sin permisos para acceder a este recurso. |
404 | Recurso no encontrado (provider, usuario o licencia inexistente). |
409 | La 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á). |
422 | Cuerpo válido pero inaplicable al estado actual del centro. Reintentable. |