# Autenticación

API keys de cuenta, permisos, entornos, revocación y qué pasa si la cuenta baja de plan.

La API pública se autentica con una **API key de cuenta**. Cada key pertenece a una sola cuenta de Posdata, y la cuenta siempre sale de la key: nunca de un parámetro, del cuerpo ni de la URL.

## Cómo enviar la key

Solo en el header `Authorization`, con el esquema `Bearer`:

```http
GET /public/v1/me HTTP/1.1
Host: api.posdata.so
Authorization: Bearer pdk_live_…
```

La API no acepta la key en la URL (`?api_key=…`): las URLs terminan en logs, historiales y encabezados `Referer`.

## Formato de la key

| Entorno    | URL base                              | Formato                     |
| ---------- | ------------------------------------- | --------------------------- |
| Producción | `https://api.posdata.so/public/v1`    | `pdk_live_` + 43 caracteres |
| Pruebas    | `https://apidev.posdata.so/public/v1` | `pdk_test_` + 43 caracteres |

- Una key de producción llamando a pruebas, o al revés, recibe `401 API_KEY_WRONG_ENVIRONMENT` con un mensaje que te dice cuál usar.
- El entorno de pruebas tiene datos de prueba y **puede reiniciarse**: úsalo para desarrollar, no para guardar información.
- En [cuenta.posdata.so](https://cuenta.posdata.so) → **Desarrolladores** ves el inicio de cada key (sus primeros caracteres) para reconocerla. Posdata guarda solo una huella (hash) de la key: si la pierdes, no hay forma de recuperarla.

## Permisos (scopes)

Cada key tiene una lista de permisos. Marca solo los que tu integración necesita: una key de solo lectura no puede cambiar nada aunque se filtre.

| Permiso           | Qué permite                                                                    |
| ----------------- | ------------------------------------------------------------------------------ |
| `products:read`   | Leer productos, variantes y categorías                                         |
| `products:write`  | Crear y editar productos, editar variantes, crear y editar categorías          |
| `customers:read`  | Leer clientes                                                                  |
| `customers:write` | Crear y editar clientes                                                        |
| `inventory:read`  | Leer bodegas, stock por bodega y movimientos de inventario                     |
| `inventory:write` | Registrar movimientos y conteos de inventario                                  |
| `inventory:costs` | Ver costos y valores del inventario (kardex valorizado y valor del inventario) |
| `sales:read`      | Leer ventas                                                                    |
| `invoices:read`   | Leer documentos electrónicos (DIAN)                                            |
| `quotes:read`     | Leer cotizaciones                                                              |
| `cash:read`       | Leer turnos y movimientos de caja                                              |
| `reports:read`    | Leer reportes agregados                                                        |
| `events:read`     | Leer el registro de eventos                                                    |

- `GET /me` funciona con cualquier key válida, sin importar sus permisos.
- Si la key no tiene el permiso de un endpoint, la respuesta es `403 INSUFFICIENT_SCOPE` y el error trae `required_scope` con el permiso que falta. Los permisos de una key no se editan: crea otra con los permisos correctos y revoca la anterior.
- Los permisos `:write` no incluyen el `:read` del mismo recurso: si vas a leer y escribir, marca ambos.
- `inventory:costs` se pide aparte porque un costo es un dato comercial sensible: con solo `inventory:read` el [kardex](https://developers.posdata.so/stock/#kardex-y-costo-promedio) trae cantidades y saldos, pero todo costo y valor viene en `null` (`costs_hidden: true`). `GET /inventory/valuation` exige `inventory:costs`. Marca `inventory:costs` solo en las integraciones que de verdad lo necesitan (contabilidad, reportes).
- Los webhooks **no** se gestionan con la API: se crean y administran solo en cuenta.posdata.so.

La página de cada endpoint en la [referencia](https://developers.posdata.so/referencia/) dice qué permiso requiere.

## Crear keys: verificación por correo

Crear una key (y crear un endpoint de webhooks o rotar su secreto) exige un **código de 6 dígitos** que llega al correo de la cuenta y vence a los 10 minutos. Así, alguien que robe la sesión de un dispositivo no puede crearse acceso permanente a tus datos. Cada vez que se crea una key o un endpoint, la cuenta recibe un correo de aviso de seguridad.

Una cuenta puede tener hasta **10 keys activas** al mismo tiempo.

## Vencimiento y revocación

- Al crearla puedes darle a la key un vencimiento de **30, 90 o 365 días**, o dejarla sin vencimiento. Una key vencida responde `401 API_KEY_EXPIRED`.
- **Revocar** una key es inmediato y no pide código: lo defensivo debe ser fácil. Una key revocada responde `401 API_KEY_REVOKED`. La revocación no se deshace.

## Si la cuenta baja de plan

La API pública está incluida en el plan **Pro** (con o sin facturación electrónica), y el plan se revisa **en cada petición**:

- Sin Pro, toda llamada responde `403 PLAN_REQUIRED`. Las keys **no se borran**: quedan en pausa y vuelven a funcionar solas cuando la cuenta recupere Pro. No tienes que crear keys nuevas.
- Los webhooks tampoco se envían mientras la cuenta no tenga Pro, y esas entregas **no se reintentan** después. Para recuperar lo que pasó en ese tiempo, usa [`GET /events`](https://developers.posdata.so/webhooks/#reconcilia-con-get-events) (el registro de eventos solo se llena mientras la cuenta tiene Pro).

## Solo desde servidores

La API es **servidor a servidor**. Cualquier petición con el header `Origin` (lo que envía un navegador) recibe `403 BROWSER_REQUESTS_NOT_ALLOWED`. Una key dentro de una página web o de una app móvil es una key pública: cualquiera puede extraerla. Si necesitas datos de Posdata en un front-end, pídelos a tu propio servidor y que él llame a la API.

La API tampoco restringe por dirección IP en esta versión.

## Buenas prácticas

- **Una key por integración.** Si tu tienda en línea y tu BI usan keys distintas, puedes revocar una sin tumbar la otra, y en **Desarrolladores → Actividad** ves qué hizo cada una.
- **Mínimo privilegio.** Un tablero de BI solo necesita permisos `:read`.
- **Rota periódicamente.** Crea la key nueva, despliégala, verifica que tus llamadas funcionan con ella (`GET /me` te dice qué key estás usando) y revoca la anterior. Las dos pueden convivir mientras cambias.
- **Guárdala como secreto** (variables de entorno o un gestor de secretos), nunca en el repositorio.
- Si sospechas que una key se filtró, **revócala de inmediato** y crea otra.

---

Fuente: https://developers.posdata.so/autenticacion/ · Índice para agentes: https://developers.posdata.so/llms.txt
