Autorizaciones de cobro
Recoger, consultar y retirar la autorización que permite cobrar a un usuario sin que esté delante: texto de consentimiento, prueba legal y alcances, en /external/v1/payment-authorizations.
Actualizado el . 5 min de lectura
Incluido en los planes Profesional y Avanzado. Ver precios
Una autorización de cobro es el consentimiento firmado con el que tu usuario te permite cargar en su tarjeta sin que esté delante. Sin ella no hay renovación mensual ni cobro programado: un cargo sin autorización es un cargo no autorizado.
Estos endpoints están bajo /external/v1/payment-authorizations, exigen la cabecera X-Api-Key y comparten un límite de 60 peticiones por minuto. Cada aplicación solo ve las autorizaciones de sus propios usuarios.
La autorización la registra tu servidor porque el usuario acepta el texto dentro de tu aplicación: tu servidor es quien conoce la dirección IP y el navegador desde los que aceptó. Esos dos datos, junto con el texto íntegro, la versión y el momento exacto, son la prueba legal del consentimiento. UTILIA OS los guarda sin posibilidad de cambio y marca al firmante como EXTERNAL.
Registrar una autorización de cobro
Participan: Tu servidor, Navegador, UTILIA OS.
De Tu servidor a UTILIA OS:
GET /api/external/v1/payment-authorizations/consent-text
Con scope RECURRING o SCHEDULED_INVOICE.De UTILIA OS a Tu servidor:
text y version (respuesta)
Con el nombre fiscal de tu organización.De Tu servidor a Navegador:
Muestra el texto tal cual
De Navegador a Tu servidor:
El usuario acepta
Guarda el momento, la IP y el navegador.De Tu servidor a UTILIA OS:
POST /api/external/v1/payment-authorizations
El mismo texto y versión, la aceptación y el setupIntentId o paymentMethodId.De UTILIA OS a Tu servidor:
201 con la autorización (respuesta)
De UTILIA OS a Tu servidor:
Aviso PAYMENT_AUTHORIZATION_GRANTED
Plan y permisos
| Concepto | Valor |
|---|---|
| Aplicativos del plan | Finanzas y Pagos con tarjeta (Stripe) |
| Capacidad del plan | Cobro automático (finance.direct_debit) |
Sin alguno de los tres, la respuesta llega antes de comprobar ningún permiso: 403 con errorCode: 'MODULE_NOT_ENABLED' y su moduleKey si falta un aplicativo, o 403 con errorCode: 'CAPABILITY_NOT_ENABLED' y su capabilityKey si falta la capacidad.
| Endpoint | Permiso de la API (scope) |
|---|---|
GET /payment-authorizations/consent-text | billing:payment-authorizations:read |
GET /payment-authorizations | billing:payment-authorizations:read |
GET /payment-authorizations/:id | billing:payment-authorizations:read |
POST /payment-authorizations | billing:payment-authorizations:write |
POST /payment-authorizations/:id/revoke | billing:payment-authorizations:revoke |
billing:payment-authorizations:write permite a la aplicación crear la prueba que autoriza cobros futuros, así que es un permiso crítico financiero: solo lo concede un Super Administrador, con un motivo que queda en la auditoría. No hay periodo de gracia: sin el permiso, la llamada responde 403 INSUFFICIENT_SCOPE desde el primer día.
Pedir el texto de consentimiento
/api/external/v1/payment-authorizations/consent-textDevuelve el texto oficial que el usuario tiene que aceptar y su versión vigente. Muéstraselo tal cual antes de que acepte.
Parámetros de consulta
- scopeenum
- RECURRING para las cuotas de una suscripción y SCHEDULED_INVOICE para cobros programados de facturas sueltas. Por defecto, RECURRING.
Respuesta (200)
{
"text": "Autorizo a Estudio Marea SL a cargar en la tarjeta indicada las cuotas de mi suscripción hasta que retire esta autorización.",
"scope": "RECURRING",
"companyName": "Estudio Marea SL",
"version": "1.2.0"
}El texto lleva el nombre fiscal de la organización, así que no lo reescribas ni lo reutilices entre organizaciones. Al registrar la autorización tendrás que devolver ese mismo texto y esa misma versión.
Registrar la autorización
/api/external/v1/payment-authorizationsRegistra la autorización que el usuario acaba de firmar dentro de tu aplicación, con la prueba de quién la aceptó y desde dónde.
Cuerpo
- userIdstringobligatorio
- Identificador en tu aplicación (externalId) del usuario que firma.
- setupIntentIdstring
- SetupIntent confirmado en el navegador del usuario, con el formato seti_…. Obligatorio salvo que envíes paymentMethodId.
- paymentMethodIdstring
- Tarjeta ya guardada del usuario. Alternativa a setupIntentId cuando la tarjeta se registró antes.
- consentTextstringobligatorio
- Texto íntegro que el usuario aceptó (máximo 4.000 caracteres). Tiene que coincidir con el que devuelve consent-text para ese mismo alcance.
- consentVersionstringobligatorio
- Versión del texto aceptado, en formato MAYOR.MENOR.PARCHE. Tiene que ser la vigente.
- acceptedAtstringobligatorio
- Momento exacto de la aceptación, en formato ISO 8601.
- acceptedIpstringobligatorio
- Dirección IP desde la que el usuario aceptó. Parte de la prueba legal.
- acceptedUserAgentstring
- Navegador desde el que aceptó, máximo 500 caracteres. Parte de la prueba legal.
- scopeenumobligatorio
- RECURRING o SCHEDULED_INVOICE. Los alcances de un solo uso los crea UTILIA OS al cobrar y no se pueden pedir desde fuera.
Respuesta (201)
{
"id": "ckauth1234567890",
"externalUserId": "user_01HXYZ",
"scope": "RECURRING",
"active": true,
"paymentMethod": {
"id": "ckpm1234567890",
"brand": "visa",
"last4": "4242",
"expMonth": 11,
"expYear": 2029
},
"consentVersion": "1.2.0",
"acceptedAt": "2026-10-01T09:10:02.000Z",
"consumedAt": null,
"revokedAt": null,
"revokedBy": null,
"createdAt": "2026-10-01T09:10:02.000Z"
}La respuesta no devuelve el número de la tarjeta ni el texto íntegro del consentimiento. Produce el aviso PAYMENT_AUTHORIZATION_GRANTED, dirigido a tu aplicación.
Cuotas y cobros sueltos necesitan dos autorizaciones
El alcance RECURRING cubre las cuotas de una suscripción. Un cobro programado de una factura suelta exige una autorización de alcance SCHEDULED_INVOICE: la primera no vale para lo segundo, y la respuesta es 409 PAYMENT_AUTHORIZATION_NOT_ACTIVE con el alcance que hace falta.
Errores
| Situación | HTTP | errorCode |
|---|---|---|
| El texto o la versión no son los vigentes | 422 | PAYMENT_AUTHORIZATION_CONSENT_MISMATCH |
Ni setupIntentId ni paymentMethodId | 400 | VALIDATION_ERROR |
| El alcance no se puede autorizar desde fuera | 400 | VALIDATION_ERROR |
| El usuario indicado no existe en la aplicación | 404 | EXTERNAL_USER_NOT_FOUND |
| La tarjeta no existe o no es de ese usuario | 404 | PAYMENT_METHOD_NOT_FOUND |
| La cuenta de la pasarela no está lista para operar | 409 | STRIPE_ACCOUNT_NOT_READY |
El consentimiento se comprueba antes de tocar la pasarela: si el texto no es el vigente, no se consume el SetupIntent.
Listar autorizaciones
/api/external/v1/payment-authorizationsLista paginada de las autorizaciones de los usuarios de la aplicación.
- userIdstring
- Filtra por el identificador del usuario en tu aplicación. Sin él se listan las de todos tus usuarios.
- scopeenum
- Filtra por alcance.
- activeboolean
- Filtra por vigencia.
- pageinteger
- Página, por defecto 1.
- limitinteger
- Elementos por página, por defecto 20 y como máximo 100.
La respuesta tiene la forma { data, total, page, limit, totalPages }.
Detalle de una autorización
/api/external/v1/payment-authorizations/:idDetalle de una autorización concreta.
Exige userId en la cadena de consulta. Si la autorización no es de ese usuario o de esa aplicación, responde 404 PAYMENT_AUTHORIZATION_NOT_FOUND.
Retirar una autorización
/api/external/v1/payment-authorizations/:id/revokeRetira la autorización. Es inmediato y arrastra todo lo que dependía de ella.
- userIdstringobligatorio
- Identificador del usuario en tu aplicación (externalId).
- reasonstring
- Motivo de la retirada, para la auditoría.
Retirar no se puede deshacer
La retirada cancela los cobros programados pendientes que dependían de la autorización y pasa a cobro manual las suscripciones que la usaban. Para volver a cobrar sin el usuario delante hay que recoger una autorización nueva.
Produce el aviso PAYMENT_AUTHORIZATION_REVOKED, dirigido a tu aplicación.
Cómo se consume una autorización
| Aviso | Qué significa |
|---|---|
PAYMENT_AUTHORIZATION_GRANTED | El usuario ha autorizado el cobro. |
PAYMENT_AUTHORIZATION_CONSUMED | Una autorización de un solo uso se ha gastado al ejecutarse el cobro que respaldaba. Deja de servir. |
PAYMENT_AUTHORIZATION_REVOKED | La autorización se ha retirado, por el usuario o por tu equipo. |
Las de alcance RECURRING no se consumen: sirven para todas las cuotas hasta que se retiren.
Con el SDK
import { UtiliaSDK } from '@utilia-os/sdk-js';
const sdk = new UtiliaSDK({
baseURL: 'https://os.utilia.ai/api',
apiKey: process.env.UTILIA_API_KEY!,
});
// 1. El texto que hay que mostrar al usuario
const consentimiento = await sdk.paymentAuthorizations.getConsentText({
scope: 'RECURRING',
});
// 2. Lo que se guarda cuando acepta
const autorizacion = await sdk.paymentAuthorizations.create({
userId: 'user_01HXYZ',
setupIntentId: 'seti_1OabcDEF',
consentText: consentimiento.text,
consentVersion: consentimiento.version,
acceptedAt: new Date().toISOString(),
acceptedIp: peticion.ip,
acceptedUserAgent: peticion.headers['user-agent'],
scope: 'RECURRING',
});
// 3. Retirarla más adelante
await sdk.paymentAuthorizations.revoke(autorizacion.id, {
userId: 'user_01HXYZ',
reason: 'El usuario la retiró desde su perfil.',
});