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

# Obtenir une table au format garanti

> Imposer les colonnes du résultat d'un run Retriever avec un contrat de sortie et un row_schema JSON Schema.

**Problème** : `artifacts` peut contenir des tables intermédiaires, avec des colonnes variables. Votre code doit toujours recevoir les mêmes champs.

**Solution** : demandez un contrat `output` de type `tables`, avec un `row_schema`.

```bash theme={null}
curl -X POST "$RETRIEVER_API_URL/v1/runs" \
  -H "Authorization: Bearer $RETRIEVER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: agences-paris-2026-09-15" \
  -d '{
    "prompt": "Trouve 20 agences de design B2B à Paris avec le nom et l email du CEO.",
    "output": {
      "type": "tables",
      "tables": [{
        "key": "agencies",
        "row_schema": {
          "type": "object",
          "required": ["company_name", "website", "ceo_name", "ceo_email"],
          "properties": {
            "company_name": { "type": "string" },
            "website": { "type": "string" },
            "ceo_name": { "type": ["string", "null"] },
            "ceo_email": { "type": ["string", "null"] }
          }
        }
      }]
    }
  }'
```

Une fois `completed` :

```python theme={null}
import os, requests

API = os.environ["RETRIEVER_API_URL"]
HEADERS = {"Authorization": f"Bearer {os.environ['RETRIEVER_API_KEY']}"}

def get(path, **params):
    res = requests.get(f"{API}{path}", headers=HEADERS, params=params, timeout=30)
    res.raise_for_status()
    return res.json()

output = get(f"/v1/runs/{run_id}/output")
agencies = next(t for t in output["tables"] if t["key"] == "agencies")

cursor = None
while True:
    page = get(agencies["links"]["rows"], limit=1000, **({"cursor": cursor} if cursor else {}))
    for row in page["items"]:
        print(row["values"]["company_name"], row["values"]["ceo_email"])
    cursor = page["next_cursor"]
    if not cursor:
        break
```

**À savoir**

* La sortie est une copie figée : elle ne change plus, même si la table source change.
* L'agent doit publier des lignes conformes au schéma, validé sans coercition. Mettez `["string", "null"]` pour tout champ qui peut manquer. Un schéma trop strict empêche la publication et le run échoue.
* Pour une seule valeur JSON (pas une table), utilisez `{"type":"json","schema":{…}}` et lisez `value` dans `GET /v1/runs/{id}/output`.
