Permisos
Cada clave lleva una lista de permisos, elegida en la creación. El formato es modulo:accion, siempre en inglés, y las acciones son read, create, update y delete.
clients:readclients:createservice_orders:updateGET /public/v1/me devuelve en key.permissions exactamente lo que la clave tiene.
Módulos y acciones
Sección titulada «Módulos y acciones»| Módulo | Permisos |
|---|---|
Clientes clients | clients:read clients:create clients:update clients:delete |
Leads leads | leads:read leads:create |
Órdenes de servicio service_orders | service_orders:read service_orders:create service_orders:update service_orders:delete |
Presupuestos quotes | quotes:read quotes:create quotes:update quotes:delete |
Ventas sales | sales:read sales:create sales:update |
Finanzas finance | finance:read finance:create finance:update finance:delete |
Agenda appointments | appointments:read appointments:create appointments:update appointments:delete |
Productos y stock products | products:read products:create products:update products:delete |
Servicios services | services:read services:create services:update services:delete |
Tareas tasks | tasks:read tasks:create tasks:update tasks:delete |
Equipo team | team:read |
Webhooks webhooks | webhooks:read webhooks:create webhooks:update webhooks:delete |
Eventos events | events:read |
No todos los módulos aceptan las cuatro acciones. sales no tiene delete porque el panel no elimina una venta, y team y events son solo de lectura.
Esta tabla sale del contrato de la API, del mismo archivo que leen el panel y el servidor. Un módulo nuevo aparece aquí solo. Tener el permiso marcado en la clave no quiere decir que la ruta de ese módulo ya exista: la Referencia es la lista de lo que responde hoy.
GET /public/v1/me responde a cualquier clave válida, sin exigir un permiso específico.
Las claves creadas en la primera versión de la API siguen valiendo: leads:write vale como leads:create, y leads:read y team:read siguen iguales.
El permiso efectivo es una intersección
Sección titulada «El permiso efectivo es una intersección»Lo que la clave puede hacer de verdad es el encuentro de cuatro cosas:
permiso de la clave ∩ rol del miembro ∩ permisos del miembro ∩ plan de la empresa
Basta con que una de ellas diga que no para que la llamada sea rechazada. Por eso una clave con clients:create todavía puede recibir un 403.
1. El permiso de la clave
Sección titulada «1. El permiso de la clave»La clave necesita el permiso que la ruta exige. Sin él, la respuesta es 403 con el código permission_missing. Una ruta pública sin permiso declarado también se rechaza: lo predeterminado es negar, nunca permitir.
La captación de lead toca dos módulos, y la clave necesita los permisos de los dos:
POST /public/v1/leadsexigeleads:create. Cuando la llamada abre la tarea de contacto, sea la predeterminada (cuerpo sintask), sea la que usted describe entask, exige tambiéntasks:create. Sin él, la respuesta es 403permission_missingy no se guarda nada, ni el lead. Contask: nullno se abre ninguna tarea, yleads:createalcanza.- Si el teléfono o el correo ya estaba registrado, la respuesta trae
deduplicated: true. En ese caso, una clave sinleads:readniclients:readrecibe solo elobjecty elid, tanto delleadcomo de latask, y no el nombre, el correo, la situación y el origen de quien ya estaba en la base. La tarea viene reducida porque su título predeterminado es “Entrar em contato com” seguido del nombre del registro existente; en el panel, el título sigue completo. Una clave que solo registra no lee clientes.
La orden de servicio también escribe en otros módulos en dos opciones, y la regla es la misma:
POST /public/v1/service_ordersconcreate_appointment: trueyscheduled_startcrea una cita en la agenda, y exige tambiénappointments:create. Sinscheduled_startno se crea ninguna cita, como en el panel, y el permiso no se exige.POST /public/v1/service_orders/{id}/completeconlink_financial_transaction: trueregistra el ingreso en finanzas, y exige tambiénfinance:create.
Sin el segundo permiso, la respuesta es 403 permission_missing y no se guarda nada: ni la orden, ni la conclusión. Sin esas dos opciones, el permiso de órdenes de servicio alcanza.
Las conversiones de presupuesto siguen la misma regla, y cada permiso extra solo se exige cuando el efecto ocurre de verdad:
POST /public/v1/quotes/{id}/convert_to_salesiempre crea una venta, y exige tambiénsales:create.- Cuando la solicitud PIDE el registro en finanzas (
track_in_finance: trueo una cuenta enpayment_plan.account_id), exige tambiénfinance:create. Cuando el campo no viene y la venta va a finanzas porque la configuración de la empresa registra las ventas (lo estándar), el permiso NO se exige: ese registro es una automatización de la empresa, como el contrato de la aprobación (vea abajo), y la pantalla del panel también deja convertir así a quien no ve finanzas. - Enviar
track_in_financeo la cuenta exige el permiso de finanzas en el miembro: la ventana de conversión del panel esconde los dos a quien no ve finanzas (403member_permission_denied). decrement_stock: truedescuenta el stock de los productos del catálogo y NO exigeproducts:update: descontar stock es parte de vender, y los caminos de venta del panel (incluido el portal del vendedor) lo descuentan sin el permiso de productos.products:*solo se exige en las rutas del propio catálogo (productos, variaciones, categorías y stock).POST /public/v1/service_orders/from_quoteexigeservice_orders:createyquotes:readen la clave, y el permiso de presupuestos en el miembro (la orden nace con el contenido del presupuesto, y convertir lo que la clave no puede leer sería hacer más de lo que haría la persona) y, concreate_appointment: trueyscheduled_start, tambiénappointments:create, como la creación de orden.
Sin el permiso extra, la respuesta es 403 permission_missing y no se guarda nada: ni la venta, ni la orden.
Las ventas siguen la misma regla. La clave necesita el permiso de ventas de la ruta y, cuando el efecto ocurre de verdad, el del módulo en el que escribe:
- Crear una venta que PIDE el registro en finanzas (
track_in_finance: trueo una cuenta enpayment_plan.account_id) exigefinance:create. Sin el campo, la venta va a finanzas por la configuración de la empresa (lo estándar), y eso NO exigefinance:create: es una automatización de la empresa, la misma que la pantalla aplica a quien no ve finanzas. El descuento de stock (decrement_stock,truepor defecto) no exigeproducts:update: es parte de vender, como en el panel. - Cobrar, anular un cobro, reprogramar cuotas, crear versión nueva y cancelar la venta son acciones de VENTAS, como la pestaña Cobros del panel, que el miembro sin finanzas opera: piden solo
sales:updateen la clave y el permiso de ventas en el miembro, incluso en una venta que está en finanzas o que descontó stock. Lo que esas acciones cambian en finanzas (movimientos) y en el stock (devolución) es automatización de la venta. - El permiso de finanzas solo entra cuando la solicitud ELIGE algo de finanzas: una cuenta (
account_iden el cobro opayment_plan.account_iden la venta y en la versión) exigefinance:readyfinance:create(en la versión,finance:update) en la clave, y el permiso de finanzas en el miembro. Decidirtrack_in_financeen la creación exige el permiso de finanzas en el miembro. La pantalla del panel esconde los dos a quien no ve finanzas.
Sin el permiso extra, la respuesta es 403 y no se guarda nada.
Finanzas usa finance:read, finance:create, finance:update y finance:delete, y el permiso de finanzas del miembro, en sus tres áreas (movimientos, cuentas y categorías):
- Leer es
finance:read. Crear movimiento, transferencia, recurrencia, cuotas, cuenta y categoría esfinance:create. Editar ymark_paidsonfinance:update. Eliminar esfinance:delete. - Los roles son los del panel: solo el dueño y los administradores crean, editan y eliminan categorías, y solo ellos eliminan cuentas. Otro rol recibe 403
member_permission_denied. mark_paiden una cuota de venta registra el cobro de la VENTA, y pide solo el permiso de finanzas: el cobro es consecuencia de la acción, como en el panel, y no exigesales:*. Es el principio de las ventas en el sentido contrario: cobrar por la venta no exigefinance:*.- Toda lectura de finanzas agenda la sincronización de las ventas con finanzas, como la pantalla. Es automatización de la empresa y no exige
sales:read.
Aprobar un presupuesto puede crear un contrato, cuando la empresa activó el contrato automático de la mensualidad. Esa creación es una automatización de la empresa, que corre igual cuando el cliente aprueba por el portal, y no pide permiso extra en la clave: quotes:update alcanza para aprobar.
2. El rol del miembro
Sección titulada «2. El rol del miembro»La clave actúa como un miembro de la empresa, elegido en la creación. Su rol vale en la API igual que en el panel:
- OWNER y ADMIN pasan por todas las áreas.
- MEMBER depende de los permisos marcados en su perfil, tanto para leer como para escribir.
- VIEWER nunca escribe. Lee las áreas que tenga marcadas.
Una clave nunca representa a un miembro con un rol superior al de quien la creó. Un ADMIN no emite una clave que actúe como OWNER.
3. Los permisos del miembro
Sección titulada «3. Los permisos del miembro»Dentro de los roles MEMBER y VIEWER, el panel marca área por área lo que la persona alcanza. La API respeta las mismas marcas. Si la persona no ve las finanzas en la pantalla, la clave que la representa no lee las finanzas por la API. El rechazo es 403 con el código member_permission_denied.
Las mismas marcas recortan listas que juntan áreas distintas. GET /public/v1/team devuelve el equipo que el panel le mostraría al miembro: técnicos solo con el permiso de técnicos, vendedores solo con el de ventas, y miembros del panel y auxiliares con el de tareas. OWNER y ADMIN ven a todos. Quien no tiene uno de esos permisos recibe la lista sin esas personas, y no un error.
Esto vale al instante. Si cambian las marcas en el panel, la llamada siguiente ya lo siente, sin esperar nada. Y si el miembro es suspendido o eliminado de la empresa, la clave deja de autenticar: la respuesta ya no es 403, pasa a ser el 401 de Autenticación.
4. El plan de la empresa
Sección titulada «4. El plan de la empresa»El plan necesita incluir la API, y las cuotas de registro del plan valen igual por la API. Los rechazos son 403 con plan_feature_unavailable (el plan no incluye el recurso) y plan_limit_reached (la cuota se agotó). Una suscripción que no está al día responde 403 con subscription_inactive.
Cómo descubrir cuál de las cuatro rechazó
Sección titulada «Cómo descubrir cuál de las cuatro rechazó»El code del error dice qué capa rechazó:
permission_missing: rechazó la clave. Cree una clave con el permiso que falta, o apunte la integración a una clave que ya lo tenga.member_permission_denied: rechazó el rol o los permisos del miembro. Ajuste el acceso de ese miembro en el panel, o emita la clave para otro miembro.plan_feature_unavailable: rechazó el plan. El plan de la empresa no incluye ese recurso.plan_limit_reached: rechazó la cuota del plan. La cuota del período se agotó.subscription_inactive: rechazó la suscripción. Regularice la suscripción en el panel.access_denied: un 403 sin causa mapeada. La API rechazó y ninguno de los códigos de arriba se aplica. Si recibe este, envíe elrequest_idal soporte.
401, 403 y 404
Sección titulada «401, 403 y 404»Las tres respuestas quieren decir cosas distintas, y la diferencia importa a la hora de depurar.
401, authentication_error. La API no sabe quién está llamando. Todo rechazo de autenticación devuelve la misma respuesta, con el código api_key_invalid. Vea Autenticación.
403, permission_error. La API sabe quién está llamando y no lo permite. Es una de las cuatro capas de arriba.
404, invalid_request_error. El recurso no existe, o existe y es de otra empresa. Un id de otra empresa responde 404, nunca 403: responder 403 confirmaría que ese id existe en algún lugar. Una ruta que no es de la API también responde 404, con el código route_not_found.
Vale la lectura directa: 401 es problema de clave, 403 es problema de derecho, 404 es problema de dirección o de id.
Cómo elegir los permisos de una clave
Sección titulada «Cómo elegir los permisos de una clave»- Marque solo lo que la integración usa. Una integración que lee clientes no necesita
clients:delete. - Una clave por integración. Revocar una no afecta a las demás, y el registro de uso muestra quién llamó a qué.
- Emita la clave para el miembro correcto. Si la integración solo necesita leer, emítala para un miembro que solo lee: así ni un error de marcado en la clave abre la escritura.