Crear una app (OAuth)
Una app es una integración que muchas empresas o comercios pueden instalar, cada uno aprobando lo que puede hacer. Si solo conectas tu propia tienda con tu propia cuenta no necesitas una: usa un token de API.
Las apps usan el flujo de código de autorización de OAuth 2.1 con PKCE. No hay SDK que aprender: cada paso es una petición HTTPS normal.
1. Abre una cuenta de desarrollador y registra una app
Entra al panel, acepta los términos para desarrolladores y registra tu app. Eliges:
- Nombre, descripción, sitio web, URL de privacidad y de soporte. Las personas las ven al aprobar.
- URI de redirección (de 1 a 10). Solo coincidencias exactas:
https://…, ohttp://localhost…mientras desarrollas. Una redirección que no está en la lista se rechaza. - Permisos (scopes) que la app puede pedir (ver Autenticación y permisos).
- Confidencial o pública. Una app de servidor es confidencial: recibe un secreto de
cliente (
aps_…) que se muestra una vez y que puedes rotar. Una app móvil o de una sola página es pública: no tiene secreto y se apoya solo en PKCE.
Recibes un client id (app_…). Es público.
Lo mismo está disponible por API en /v1/developer/… para personas con sesión (no para tokens).
2. Envía a la persona a aprobar
Abre el navegador de la persona en la página de consentimiento de la aplicación web, con un reto
PKCE y un state que verificarás al volver:
https://cloud.antivio.app/oauth/authorize
?response_type=code
&client_id=app_Ab3xK9mQ2wL7pZ4nR8tY1vC5
&redirect_uri=https%3A%2F%2Facme.example%2Foauth%2Fcallback
&scope=shipments%3Aread%20shipments%3Awrite
&state=<texto aleatorio que guardas>
&code_challenge=<base64url(sha256(code_verifier))>
&code_challenge_method=S256
Crea un code_verifier nuevo (de 43 a 128 caracteres de A-Z a-z 0-9 - . _ ~) en cada intento y
guárdalo en tu servidor (o en la sesión). state y PKCE son obligatorios.
La persona inicia sesión, elige la empresa (o la cuenta de comercio) y aprueba los permisos. Solo quienes pueden gestionar integraciones ahí pueden instalar una app, y solo pueden dar permisos que su propio rol tiene. Antivio redirige el navegador a tu URI:
https://acme.example/oauth/callback?code=atc_…&state=<tu state>
Si rechaza, la redirección trae error=access_denied y tu state. Verifica state antes de
usar el código. El código sirve una vez y durante 60 segundos.
3. Cambia el código por tokens
curl -X POST https://api.antivio.app/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=authorization_code \
-d code="$CODE" \
-d redirect_uri="https://acme.example/oauth/callback" \
-d code_verifier="$CODE_VERIFIER"
Las apps confidenciales se autentican con HTTP Basic (arriba) o con client_id y client_secret
en el cuerpo del formulario; las públicas envían solo client_id.
{
"access_token": "atk_live_…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "atr_…",
"scope": "shipments:read shipments:write"
}
El token de acceso es el mismo bearer que un token de API: envíalo como Authorization: Bearer …
a la API pública. Actúa como la persona que aprobó,
limitado a los permisos otorgados, así que deja de funcionar si esa persona sale de la empresa.
Dura una hora.
4. Renueva
curl -X POST https://api.antivio.app/oauth/token -u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=refresh_token -d refresh_token="$REFRESH_TOKEN"
Cada renovación devuelve un token de renovación nuevo y gasta el anterior. Guarda el nuevo antes de usar el nuevo token de acceso. Los tokens de renovación duran 30 días.
Si un token de renovación o un código se usa dos veces, Antivio asume que se filtró y revoca todos los tokens de esa instalación; la persona debe aprobar de nuevo. No reintentes una renovación en paralelo.
5. Revoca
curl -X POST https://api.antivio.app/oauth/revoke -u "$CLIENT_ID:$CLIENT_SECRET" \
-d token="$REFRESH_TOKEN"
Revocar un token de acceso termina solo ese token; revocar un token de renovación termina todos
los de la instalación. La respuesta es 200 incluso para un token que no conocemos.
6. Recibe webhooks
Con webhooks:write, tu token de acceso agrega endpoints de webhooks como
cualquier token de API (POST /v1/webhook-endpoints). Pertenecen a la instalación:
- tu token ve y cambia solo los endpoints que agregó (
installation_idindica cuáles), nunca los propios de la empresa; cuentan para un límite de 5 por instalación; - la empresa los ve en su configuración de Desarrolladores y puede quitarlos;
- desinstalar tu app los elimina, y mientras Antivio suspende tu app no reciben nada.
7. Eventos de la app y solicitudes de privacidad
Configura la URL de eventos de tu app en el portal de desarrolladores (o
PUT /v1/developer/apps/{id}/events con {"url": "https://…"}). Antivio envía ahí, por cada
empresa que instaló tu app, mensajes firmados con el secreto de eventos de tu app (whsec_…,
visible en el portal) igual que los webhooks: verifica webhook-signature con el
mismo código, responde 2xx y usa webhook-id para ignorar repeticiones. Los mensajes fallidos se
reintentan durante unos tres días.
| Tipo | Cuándo | data |
|---|---|---|
app.uninstalled | la empresa quitó tu app; sus tokens y endpoints de webhooks ya no existen | installation_id, customer_account_id, uninstalled_at |
customer.data_request | un destinatario pidió a la empresa los datos que se guardan sobre él | privacy_request_id, installation_id, customer_account_id, recipient (email, phone), shipment_ids, requested_at |
customer.redact | un destinatario pidió que se borren sus datos | lo mismo que customer.data_request |
- La respuesta de tokens incluye
installation_id,tenant_idycustomer_account_id: guárdalos para relacionar estos mensajes con tus registros. Eltenant_iddel sobre es la empresa. - Ante
customer.data_request, envía a la empresa lo que tu app guarda sobre esa persona; antecustomer.redact, bórralo (conserva solo lo que la ley te obligue).shipment_idsson los envíos de ese destinatario que tu instalación puede ver (como máximo 500). - Rota el secreto en el portal: el anterior sigue firmando durante 24 horas. El portal también muestra los últimos mensajes y su estado.
8. Publica en la App Store
Una app privada se instala desde un enlace que compartes, sin revisión. Para que cualquier empresa la encuentre e instale, envíala a revisión; cuando Antivio la aprueba, aparece en la App Store dentro del panel de cada empresa.
Antes de enviarla, la app necesita una URL de política de privacidad, una URL de soporte y una
URL de eventos (debe recibir app.uninstalled
y las solicitudes de privacidad). Luego:
curl -X POST https://api.antivio.app/v1/developer/apps/$APP_ID/submissions \
-H "Authorization: Bearer $USER_TOKEN" -H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" -d '{
"listing": {
"tagline": "Mantén los pedidos y envíos de tu tienda sincronizados",
"description_en": "Sends every order to Antivio and brings the tracking back.",
"description_es": "Envía cada pedido a Antivio y trae el seguimiento.",
"category": "ecommerce",
"app_url": "https://acme.example/install",
"scope_justifications": [
{ "scope": "shipments:read", "justification": "Muestra el estado de cada pedido al comprador." }
]
},
"note": "Primera versión."
}'
app_urles donde empieza la instalación: una página de tu app que inicia el flujo OAuth descrito arriba. El botón Instalar de la tienda la abre. Antivio nunca envía un código de autorización a una app que no lo pidió.- Cada permiso necesita una justificación (20-300 caracteres) con tus palabras. Las empresas la ven antes de instalar.
- Un envío es una instantánea: el listado y el nombre, la descripción, las URL, las URI de
redirección, los permisos y la URL de eventos de la app tal como se enviaron. Envía
"app": {...}y"events_url"para proponer valores nuevos. - Las verificaciones automáticas corren al enviar y el revisor ve los resultados: tus páginas de
privacidad, soporte y
app_urlresponden; tu URL de eventos rechaza un mensaje con firma incorrecta (responde4xx) y acepta un mensaje de pruebaapp.uninstalledbien firmado (responde2xx,"test": true, sin empresa real). Una verificación fallida no rechaza la app por sí sola, pero un revisor te pedirá corregirla. Los resultados están enchecksde cada envío. - Estados:
submitted→in_review→approved|rejected|changes_requested; puedes retirarlo (withdraw) mientras espera.GET /v1/developer/apps/{id}/submissionsmuestra el estado y la nota del revisor. Tras 3 rechazos en 90 días los nuevos envíos esperan 30 días. - Una vez publicada, los campos revisados de la app quedan bloqueados
(
409 app.published_requires_review): para cambiar sus permisos, URI de redirección, URL o URL de eventos, envía una actualización. Hasta que se apruebe, la app y la tienda conservan lo aprobado. Las empresas que ya la instalaron conservan los permisos que concedieron. POST /v1/developer/apps/{id}/unpublishla saca de la tienda y la vuelve privada; las empresas que la instalaron la conservan. Antivio también puede retirar o suspender una app que incumpla las reglas; los tokens, eventos y webhooks de una app suspendida se detienen al instante.
Errores
El endpoint de tokens responde con errores de RFC 6749, no con problemas RFC 9457:
error | Estado | Significado |
|---|---|---|
invalid_request | 400 | Falta un parámetro o es inválido (forma del code_verifier, cuerpo del formulario) |
invalid_client | 401 | App desconocida, suspendida o mal autenticada |
invalid_grant | 400 | El código o el token de renovación es desconocido, ya usado, vencido o de otra app o URI; o la app fue desinstalada |
unsupported_grant_type | 400 | Solo existen authorization_code y refresh_token. No hay concesión por contraseña, implícita ni de credenciales de cliente |
Metadatos del servidor
GET /.well-known/oauth-authorization-server (RFC 8414)
lista los endpoints, S256 y los permisos soportados.
Buenas prácticas
- Guarda el secreto de cliente en tu servidor. Si se filtra, rótalo desde el panel: el anterior deja de funcionar al instante.
- Solo se acepta PKCE
S256. Verifica siemprestate. - Trata un
invalid_grantal renovar como "la persona debe aprobar de nuevo".