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

# Integrazioni partner di Outposts

> Connetti un outpost da una piattaforma partner con uno scambio di codici PKCE

<Note>
  Note preliminari — questo flusso è nelle prime fasi di sviluppo e i dettagli
  riportati di seguito potrebbero cambiare.
</Note>

Le piattaforme partner (ad es. i provider di calcolo) possono connettere un outpost per conto di un cliente. L'admin di Devin del cliente autorizza la connessione nel browser; Devin crea quindi un outpost e un utente di servizio e fornisce al partner un token per eseguire i worker sull'outpost.

Il flusso è uno scambio di codice di autorizzazione OAuth semplificato con [PKCE](https://datatracker.ietf.org/doc/html/rfc7636). Nel browser transita solo un **codice** monouso e di breve durata: il token dell'utente di servizio viene scambiato da server a server e non passa mai dal browser.

<div id="prerequisites">
  ## Prerequisiti
</div>

* **Allowlist dei callback.** Ogni `callback_url` che utilizzi deve essere presente nell'allowlist di Devin per la tua integrazione. La configurazione viene effettuata da Cognition: inviaci in anticipo gli URL esatti. Qualsiasi URL non presente nell'elenco verrà rifiutato.
* **Outposts abilitato.** L'account del cliente deve avere Outposts abilitato.
* **Autorizzazione admin.** Per autorizzare una connessione è necessario un admin di Devin con diritti sia su `enterprise-settings` sia sulla gestione dei `utenti di servizio`. Il partner non ha mai bisogno di un token Devin: l'admin autorizza la connessione nella propria sessione del browser.

<div id="flow-overview">
  ## Panoramica del flusso
</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 verifier e una challenge PKCE
</div>

Nel backend, per ogni tentativo di connessione:

* Genera un **`code_verifier`** casuale ad alta entropia: 43–128 caratteri dall'alfabeto non riservato `[A-Za-z0-9-._~]` (ad es. `base64url(random 32 bytes)` con il padding rimosso).
* Deriva il **`code_challenge`** come base64url senza padding dello SHA-256 del verifier (PKCE "S256"):

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

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

Conserva `code_verifier` lato server (associandolo allo stato che usi per correlare l'eventuale callback). Non inviare mai `code_verifier` al browser: dal tuo backend deve uscire solo il challenge.

<div id="2-redirect-the-admin-to-the-connect-page">
  ### 2. Reindirizza l'admin alla pagina Connect
</div>

Invia l'admin del cliente alla pagina Connect di Devin con la challenge e il tuo 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>
```

| Parametro        | Obbligatorio | Note                                                                                            |
| ---------------- | ------------ | ----------------------------------------------------------------------------------------------- |
| `callback_url`   | sì           | URL a cui Devin inoltra il codice una tantum. Deve essere nella tua allowlist.                  |
| `code_challenge` | sì           | Il valore PKCE S256 challenge del passaggio 1.                                                  |
| `outpost_name`   | no           | Nome suggerito dell'outpost. L'admin può modificarlo prima di confermare.                       |
| `outpost_image`  | no           | URL di un'icona PNG usata per rappresentare l'outpost, come il logo della tua azienda.          |
| `platform`       | no           | Piattaforma dell'outpost preselezionata: `macos`, `linux` o `windows`. L'admin può modificarla. |

Se l'admin non ha effettuato l'accesso, la pagina Connect salva questi parametri e gli chiede prima di accedere, quindi riprende il processo.

<div id="3-admin-confirms">
  ### 3. L'admin conferma
</div>

La pagina Connect mostra una schermata di conferma con un nome dell'outpost e una piattaforma modificabili (e il tuo `outpost_image`, se fornito). Quando l'admin fa clic su **Connect**, Devin verifica le autorizzazioni, l'allowlist dei callback e che il nome dell'outpost non sia già in uso, memorizza un codice crittografato monouso (TTL di 10 minuti) e reindirizza alla tua app con il codice una tantum.

Non esistono ancora né un outpost né un utente di servizio: vengono creati solo quando il codice viene riscattato (passaggio 5). Un codice non riscattato scade semplicemente.

<div id="4-devin-redirects-the-code-to-your-callback">
  ### 4. Devin reindirizza il codice al callback
</div>

Il browser viene reindirizzato a `callback_url` con il codice aggiunto:

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

<div id="5-exchange-the-code-server-to-server">
  ### 5. Scambia il codice tra server
</div>

Dal tuo backend, recupera il `code_verifier` che hai archiviato nel passaggio 1 e scambia il codice presso l'endpoint del token. Si tratta di una richiesta di token in stile OAuth con codifica form:

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

Questo endpoint non richiede l'autenticazione Devin — il possesso del codice insieme al verifier PKCE corrispondente ne è la prova. Non è autenticato volutamente: il codice è monouso (consumato in modo atomico), ha una durata breve ed è vincolato alla tua challenge.

<div id="6-receive-the-credentials">
  ### 6. Ricevi le credenziali
</div>

In caso di esito positivo, Devin crea l'outpost e un utente di servizio con l'ambito necessario per eseguire l'outpost worker e restituisce:

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

Le risposte includono `Cache-Control: no-store` — non metterle in cache.

<div id="7-run-outpost-workers">
  ### 7. Eseguire gli outpost worker
</div>

Memorizzare `access_token` e `api_base_url` in modo sicuro e usare il token come credenziale bearer per eseguire gli outpost worker sull'outpost.

<div id="error-handling">
  ## Gestione degli errori
</div>

L'endpoint del token segue [RFC 6749 §5.2](https://datatracker.ietf.org/doc/html/rfc6749#section-5.2). Un codice sconosciuto, scaduto, già utilizzato (replayed) o con PKCE non corrispondente restituisce `400`:

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

Poiché i codici sono monouso e scadono dopo 10 minuti, considera qualsiasi `invalid_grant` come definitivo: elimina il `code_verifier` memorizzato e riavvia il flusso dal passaggio 1.

<div id="security-notes">
  ## Note sulla sicurezza
</div>

* **Il token non passa mai dal browser.** Solo il codice monouso viene inoltrato tramite redirect; il token dell’utente di servizio viene restituito esclusivamente dallo scambio da server a server.
* **PKCE vincola il codice a te.** Il codice è inutilizzabile senza il `code_verifier`, conservato solo nel tuo backend, quindi intercettare il redirect (o il codice) non basta per utilizzarlo.
* **I codici sono monouso e di breve durata.** Il riscatto consuma il codice in modo atomico; inoltre, scade dopo 10 minuti.
* **Le callback URL sono nell'allowlist.** Devin inoltra un codice a un `callback_url` solo se Cognition lo ha pre-approvato per la tua integrazione.
* **Verifica che il codice sia per l’utente che ha effettuato la richiesta.** Conferma che il codice restituito alla tua callback appartenga allo stesso utente che ha richiesto originariamente la connessione. Questo impedisce a un attaccante di indurre un utente, a sua insaputa, a vincolare Devin a un sandbox controllato dall’attaccante.
* **Mantieni `outpost_name` sensato.** L'admin può applicare un override; il nome che passi è solo un suggerimento.
