> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Integraciones de socios para Outposts

> Conectar un outpost desde una plataforma asociada con un intercambio de código PKCE

<Note>
  Notas preliminares: este flujo está en una fase temprana de desarrollo y los detalles que aparecen a continuación pueden
  cambiar.
</Note>

Las plataformas asociadas (p. ej., proveedores de cómputo) pueden conectar un outpost en nombre de un cliente. El Admin de Devin del cliente autoriza la conexión en el navegador; luego Devin crea un outpost y un usuario de servicio, y entrega al socio un token para ejecutar workers en el outpost.

El flujo es un intercambio de código de autorización similar a OAuth con [PKCE](https://datatracker.ietf.org/doc/html/rfc7636). El navegador solo transporta un **código** de corta duración y de un solo uso: el token del usuario de servicio se intercambia de servidor a servidor y nunca pasa por el navegador.

<div id="prerequisites">
  ## Requisitos previos
</div>

* **Lista de permitidos de callback.** Todos los `callback_url` que uses deben estar en la lista de permitidos de Devin para tu integración. Cognition se encarga de configurarlo; envíanos las URL exactas con antelación. Cualquier URL que no esté en la lista será rechazada.
* **Outposts habilitado.** La cuenta del cliente debe tener Outposts habilitado.
* **Autorización de Admin.** Para autorizar una conexión, se necesita un Admin de Devin con permisos de enterprise-settings y de gestión de usuario de servicio. El socio nunca necesita un token de Devin: el Admin lo autoriza desde su propia sesión del navegador.

<div id="flow-overview">
  ## Resumen del flujo
</div>

```
Partner backend                 Admin's browser                 Devin
     │                                │                            │
     │ 1. gen code_verifier,          │                            │
     │    derive code_challenge       │                            │
     │ 2. redirect to app.devin.ai/outposts/connect?…code_challenge│
     │───────────────────────────────>                            │
     │                                │ 3. admin confirms, "Connect"│
     │                                │──────confirm connection──────>
     │                                │ 4. redirect callback_url?code=…  │
     │<───────────────────────────────                            │
     │ 5. POST /outposts/connection-token  (code + code_verifier) │
     │────────────────────────────────────────────────────────────>
     │ 6. { access_token, api_base_url, … }                       │
     │<────────────────────────────────────────────────────────────
     │ 7. run outpost workers with access_token                   │
```

<div id="1-generate-a-pkce-verifier-and-challenge">
  ### 1. Genera un verificador y un desafío de PKCE
</div>

En tu backend, por cada intento de conexión:

* Genera un **`code_verifier`** aleatorio y de alta entropía: de 43 a 128 caracteres del alfabeto no reservado `[A-Za-z0-9-._~]` (p. ej., `base64url(random 32 bytes)` sin relleno).
* Deriva el **`code_challenge`** como el valor base64url sin relleno del SHA-256 del verificador (PKCE "S256"):

```python theme={null}
import base64, hashlib, secrets

code_verifier = secrets.token_urlsafe(32)  # 43+ caracteres, alfabeto no reservado
code_challenge = (
    base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest())
    .rstrip(b"=")
    .decode()
)
```

Almacena `code_verifier` en el servidor (asociado con el estado que uses para correlacionar la devolución de llamada cuando se produzca). Nunca envíes el verificador al navegador: solo el desafío sale de tu backend.

<div id="2-redirect-the-admin-to-the-connect-page">
  ### 2. Redirige al Admin a la página de conexión
</div>

Envía al Admin del cliente a la página de conexión de Devin con el desafío y tu callback:

```
https://app.devin.ai/outposts/connect
  ?callback_url=https://partner.example.com/devin/outpost-callback
  &outpost_name=my-outpost
  &outpost_image=https://partner.example.com/logo.png
  &platform=linux
  &code_challenge=<code_challenge>
```

| Param            | Obligatorio | Notas                                                                                           |
| ---------------- | ----------- | ----------------------------------------------------------------------------------------------- |
| `callback_url`   | sí          | Donde Devin envía el código único. Debe estar en tu lista de permitidos.                        |
| `code_challenge` | sí          | El desafío PKCE S256 del paso 1.                                                                |
| `outpost_name`   | no          | Nombre sugerido del outpost. El Admin puede editarlo antes de confirmarlo.                      |
| `outpost_image`  | no          | URL de un icono PNG usado para representar el outpost, como el logotipo de tu empresa.          |
| `platform`       | no          | Plataforma del outpost preseleccionada: `macos`, `linux` o `windows`. El Admin puede cambiarla. |

Si el Admin no ha iniciado sesión, la página de conexión guarda estos parámetros y le pide que primero inicie sesión; luego, reanuda el proceso.

<div id="3-admin-confirms">
  ### 3. Admin confirma
</div>

La página de conexión muestra una confirmación con un nombre de outpost editable y una plataforma (y tu `outpost_image`, si se proporciona). Cuando el Admin hace clic en **Connect**, Devin valida los permisos, la lista de permitidos del callback y que el nombre del outpost esté disponible, almacena un código cifrado de un solo uso (TTL de 10 minutos) y redirige de nuevo a tu app con el código de un solo uso.

Todavía no existe ningún outpost ni ningún usuario de servicio; solo se crean cuando se canjea el código (paso 5). Un código sin canjear simplemente caduca.

<div id="4-devin-redirects-the-code-to-your-callback">
  ### 4. Devin redirige el código a tu URL de callback
</div>

El navegador se redirige a tu `callback_url` con el código adjunto:

```
https://partner.example.com/devin/outpost-callback?code=<one-time code>
```

<div id="5-exchange-the-code-server-to-server">
  ### 5. Intercambia el código entre servidores
</div>

Desde tu backend, recupera el `code_verifier` que almacenaste en el paso 1 y canjea el código en el endpoint de token. Esta es una solicitud de token codificada como formulario, al estilo de OAuth:

```bash theme={null}
curl -X POST "https://api.devin.ai/outposts/connection-token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "code=<one-time code>" \
  --data-urlencode "code_verifier=<code_verifier>"
```

Este endpoint no requiere autenticación de Devin: la posesión del código junto con el verificador PKCE correspondiente es prueba suficiente. No requiere autenticación a propósito: el código es de un solo uso (se consume de forma atómica), tiene una vida útil corta y está vinculado a tu desafío.

<div id="6-receive-the-credentials">
  ### 6. Recibir las credenciales
</div>

Si la operación se realiza correctamente, Devin crea el outpost y un usuario de servicio con el ámbito necesario para ejecutar el worker de outpost, y devuelve:

```json theme={null}
{
  "outpost_id": "...",
  "account_id": "...",
  "outpost_name": "my-outpost",
  "service_user_id": "...",
  "api_base_url": "https://api.devin.ai",
  "access_token": "cog_...",
  "token_type": "bearer"
}
```

Las respuestas incluyen `Cache-Control: no-store` — no las almacenes en caché.

<div id="7-run-outpost-workers">
  ### 7. Ejecuta workers de outpost
</div>

Almacena `access_token` y `api_base_url` de forma segura y usa el token como credencial bearer para ejecutar workers de outpost en el outpost.

<div id="error-handling">
  ## Manejo de errores
</div>

El endpoint de token sigue [RFC 6749 §5.2](https://datatracker.ietf.org/doc/html/rfc6749#section-5.2). Un código desconocido, caducado, ya canjeado (reutilizado) o que no coincide con PKCE devuelve `400`:

```json theme={null}
{
  "error": "invalid_grant",
  "error_description": "Invalid or expired connection code"
}
```

Dado que los códigos son de un solo uso y caducan a los 10 minutos, trata cualquier `invalid_grant` como definitivo: descarta el `code_verifier` almacenado y reinicia el flujo desde el paso 1.

<div id="security-notes">
  ## Notas de seguridad
</div>

* **El token nunca pasa por el navegador.** Solo se retransmite el código de un solo uso mediante la redirección; el token del usuario de servicio se devuelve únicamente en el intercambio entre servidores.
* **PKCE vincula el código con tu backend.** El código es inútil sin el `code_verifier`, que solo está en tu backend, así que interceptar la redirección (o el código) no basta para canjearlo.
* **Los códigos son de un solo uso y caducan pronto.** El canje consume el código de forma atómica; además, caduca a los 10 minutos.
* **Las URL de callback están en la lista de permitidos.** Devin solo retransmite un código a una `callback_url` que Cognition haya aprobado previamente para tu integración.
* **Verifica que el código corresponda al usuario solicitante.** Confirma que el código devuelto a tu callback pertenece al mismo usuario que solicitó originalmente la conexión. Esto evita que un atacante engañe a un usuario para que, sin darse cuenta, vincule Devin a un sandbox controlado por el atacante.
* **Mantén `outpost_name` razonable.** El Admin puede anularlo; el nombre que pases es solo una sugerencia.
