> ## 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.

# Intégrations partenaires Outposts

> Connecter un outpost depuis une plateforme partenaire avec un échange de code PKCE

<Note>
  Notes préliminaires — ce flux est encore en cours de développement et les
  détails ci-dessous peuvent évoluer.
</Note>

Les plateformes partenaires (p. ex. des fournisseurs de calcul) peuvent connecter un outpost pour le compte d’un client. L’administrateur Devin du client autorise la connexion dans le navigateur ; Devin crée ensuite un outpost et un utilisateur de service, puis remet au partenaire un token pour exécuter des workers sur l’outpost.

Le flux est un échange de code d’autorisation OAuth simplifié avec [PKCE](https://datatracker.ietf.org/doc/html/rfc7636). Le navigateur ne transporte qu’un **code** à courte durée de vie et à usage unique — le token de l’utilisateur de service est échangé de serveur à serveur et ne transite jamais par le navigateur.

<div id="prerequisites">
  ## Prérequis
</div>

* **Liste d’autorisation des rappels.** Chaque `callback_url` que vous utilisez doit figurer dans la liste d’autorisation de Devin pour votre intégration. Cette configuration est effectuée par Cognition — envoyez-nous à l’avance les URL exactes. Toute URL qui ne figure pas dans la liste est rejetée.
* **Outposts activé.** Le compte du client doit avoir Outposts activé.
* **Autorisation administrateur.** L’autorisation d’une connexion nécessite un administrateur Devin disposant à la fois des droits enterprise-settings et des droits de gestion des utilisateurs de service. Le partenaire n’a jamais besoin d’un jeton Devin — l’administrateur l’autorise depuis sa propre session de navigateur.

<div id="flow-overview">
  ## Vue d’ensemble du flux
</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. Générer un vérificateur et un challenge PKCE
</div>

Sur votre backend, pour chaque tentative de connexion :

* Générez un **`code_verifier`** aléatoire à forte entropie : 43 à 128 caractères issus de l'alphabet non réservé `[A-Za-z0-9-._~]` (p. ex. `base64url(random 32 bytes)` sans remplissage).
* Dérivez le **`code_challenge`** en encodant en base64url, sans remplissage, le SHA-256 du vérificateur (PKCE "S256") :

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

code_verifier = secrets.token_urlsafe(32)  # 43+ caractères, alphabet non réservé
code_challenge = (
    base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest())
    .rstrip(b"=")
    .decode()
)
```

Stockez le `code_verifier` côté serveur (en l’associant à la valeur `state` que vous utilisez pour faire le lien avec le callback ultérieur). N’envoyez jamais le `code_verifier` au navigateur — seul le challenge quitte votre backend.

<div id="2-redirect-the-admin-to-the-connect-page">
  ### 2. Redirigez l’administrateur vers la page Connect
</div>

Envoyez l’administrateur du client vers la page Connect de Devin avec le challenge et votre URL de rappel :

```
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            | Requis | Remarques                                                                                                |
| ---------------- | ------ | -------------------------------------------------------------------------------------------------------- |
| `callback_url`   | oui    | Là où Devin transmet le code à usage unique. Doit figurer dans votre liste d’autorisation.               |
| `code_challenge` | oui    | Le challenge PKCE S256 de l’étape 1.                                                                     |
| `outpost_name`   | non    | Nom d’outpost suggéré. L’administrateur peut le modifier avant de confirmer.                             |
| `outpost_image`  | non    | URL d’une icône PNG utilisée pour représenter l’outpost, comme le logo de votre entreprise.              |
| `platform`       | non    | Plateforme d’outpost présélectionnée : `macos`, `linux` ou `windows`. L’administrateur peut la modifier. |

Si l’administrateur n’est pas connecté, la page Connect conserve ces paramètres et lui demande d’abord de se connecter, puis reprend le processus.

<div id="3-admin-confirms">
  ### 3. L’administrateur confirme
</div>

La page Connect affiche une confirmation avec un nom d’outpost et une plateforme modifiables (ainsi que votre `outpost_image` si fournie). Lorsque l’administrateur clique sur **Connect**, Devin vérifie les autorisations, la liste d’autorisation de rappel et la disponibilité du nom de l’outpost, stocke un code chiffré à usage unique (TTL de 10 minutes), puis redirige vers votre application avec le code à usage unique.

Aucun outpost ni utilisateur de service n’existe encore — ils ne sont créés qu’au moment où le code est échangé (étape 5). Un code non échangé expire simplement.

<div id="4-devin-redirects-the-code-to-your-callback">
  ### 4. Devin redirige le code vers votre URL de callback
</div>

Le navigateur est redirigé vers votre `callback_url`, avec le code ajouté :

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

<div id="5-exchange-the-code-server-to-server">
  ### 5. Échangez le code côté serveur
</div>

Depuis votre backend, récupérez le `code_verifier` que vous avez stocké à l’étape 1, puis échangez le code auprès de l’endpoint token. Il s’agit d’une requête de token de type OAuth, encodée au format de formulaire :

```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>"
```

Cet endpoint ne nécessite pas d’authentification Devin — la possession du code et du vérificateur PKCE correspondant suffit comme preuve. C’est intentionnellement non authentifié : le code est à usage unique (consommé atomiquement), valable peu de temps et lié à votre challenge.

<div id="6-receive-the-credentials">
  ### 6. Récupérer les identifiants
</div>

En cas de succès, Devin crée l’outpost ainsi qu’un utilisateur de service avec le périmètre nécessaire pour exécuter le worker Outpost, puis renvoie :

```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"
}
```

Les réponses comportent `Cache-Control: no-store` — ne les mettez pas en cache.

<div id="7-run-outpost-workers">
  ### 7. Exécuter les workers Outpost
</div>

Stockez `access_token` et `api_base_url` de manière sécurisée, puis utilisez le token comme jeton Bearer pour exécuter les workers Outpost sur l’Outpost.

<div id="error-handling">
  ## Gestion des erreurs
</div>

L’endpoint `token` suit la [RFC 6749 §5.2](https://datatracker.ietf.org/doc/html/rfc6749#section-5.2). Un code inconnu, expiré, déjà utilisé (rejoué) ou non conforme à PKCE renvoie `400` :

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

Comme les codes sont à usage unique et expirent au bout de 10 minutes, considérez tout `invalid_grant` comme définitif : supprimez le `code_verifier` stocké et redémarrez le flux à partir de l'étape 1.

<div id="security-notes">
  ## Notes de sécurité
</div>

* **Le token ne transite jamais par le Browser.** Seul le code à usage unique est relayé via la redirection ; le token de l’utilisateur de service n’est renvoyé que lors de l’échange de serveur à serveur.
* **PKCE lie le code à votre backend.** Le code est inutilisable sans le `code_verifier`, conservé uniquement sur votre backend ; intercepter la redirection (ou le code) ne suffit donc pas pour l’échanger.
* **Les codes sont à usage unique et de courte durée.** Leur échange consomme le code de manière atomique ; il expire également au bout de 10 minutes.
* **Les URL de rappel figurent sur la liste d’autorisation.** Devin ne relaie un code qu’à une `callback_url` que Cognition a préalablement approuvée pour votre intégration.
* **Vérifiez que le code correspond bien à l’utilisateur demandeur.** Assurez-vous que le code renvoyé à votre URL de rappel appartient au même utilisateur que celui qui a initialement demandé la connexion. Cela empêche un attaquant d’amener un utilisateur à lier Devin, à son insu, à un sandbox contrôlé par l’attaquant.
* **Gardez un `outpost_name` pertinent.** L’administrateur peut le remplacer via une dérogation ; le nom que vous transmettez n’est qu’une suggestion.
