# marches_dce_lien_obtenir

URL de telechargement signee (valable 1 h) d'une piece de DCE, ou de l'archive complete du dossier. { marche_id } (UUID de marche OU annonce_id) telecharge le dossier entier ; ajouter { filename } cible une piece precise si elle est stockee isolement. Renvoie une erreur honnete si le dossier n'est pas heberge chez Prescriptio (jamais de lien mort ni de lien vers la plateforme externe).

| | |
|---|---|
| Effets | lecture seule |
| Portée OAuth | `mcp:read` |
| Offre requise | aucune — ouvert à tous les comptes |
| Données lues | la donnée publique du bâti — aucune coordonnée personnelle n'est jamais renvoyée |
| Distribution | connecteurs ChatGPT/Claude (`connectors-1.0.0`) et MCP historique |

Cet outil est aussi distribué en REST : `POST /api/mcp/v1/dce.download` (portée `mcp:read`), documenté sur [dce.download](/docs/api/dce.download.md).

## Paramètres

| Paramètre | Type | Requis | Bornes | Description |
|---|---|---|---|---|
| `filename` | texte | — | — | Nom exact d'une piece a telecharger (facultatif). Omis, ou piece non stockee isolement : l'archive complete du dossier est renvoyee. |
| `marche_id` | texte | oui | — | Identifiant du dossier : UUID de marche OU annonce_id betterplace (ex "2833189"). |

## Exemple d'appel

_exemple synthétique du contrat REST, adapté à l'action MCP._

```json
{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "marche_id": "fixture-dce-001"
    },
    "name": "marches_dce_lien_obtenir"
  }
}
```

En HTTP, c'est ce corps que l'on poste :

```bash
curl -sS https://prescriptio.fr/api/mcp \
  -H 'Authorization: Bearer <jeton>' \
  -H 'Content-Type: application/json' \
  -d '{"id":1,"jsonrpc":"2.0","method":"tools/call","params":{"arguments":{"marche_id":"fixture-dce-001"},"name":"marches_dce_lien_obtenir"}}'
```

## Forme de la réponse

Le résultat est enveloppé par le protocole : un bloc `content[0].text` qui porte le JSON sérialisé, et `structuredContent` qui porte le même objet. Le squelette ci-dessous donne les **types**, jamais des valeurs réelles.

```json
{
  "action": "telechargement_dce",
  "content_type": "<texte>",
  "count": 0,
  "doc_type": "<texte>",
  "download_url": "<texte>",
  "expires_in": 0,
  "fichiers": [
    {
      "filename": "<texte>",
      "pages_estimees": 0,
      "parties": 0
    }
  ],
  "fields": {},
  "filename": "<texte>",
  "hint": "<texte>",
  "marche_id": "<texte>",
  "ok": true,
  "page": 0,
  "pages_total": 0,
  "query": "<texte>",
  "results": [
    {
      "acheteur": "<texte>",
      "doc_type": "<texte>",
      "extrait": "<texte>",
      "filename": "<texte>",
      "lieu": "<texte>",
      "marche_id": "<texte>",
      "titre": "<texte>"
    }
  ],
  "texte": "<texte>",
  "titre": "<texte>"
}
```

Un champ absent ou `null` n'est ni un zéro ni une estimation : la source ne l'a pas renseigné. Les propriétés additionnelles restent autorisées ; ce squelette n'invente pas les champs manquants.

## Erreurs

Le connecteur MCP renvoie une erreur JSON-RPC pour ce qui empêche l'appel, et une erreur *métier* (`isError`) lisible par le modèle pour ce que l'appel n'a pas pu faire.

| Code JSON-RPC | Quand | Que faire |
|---|---|---|
| `-32601` | Outil inconnu | Appeler `tools/list` ; ne pas deviner un nom |
| `-32602` | Argument absent ou hors schéma | Corriger l'argument nommé dans le message |
| `-32003` | Portée OAuth absente de l'autorisation | Reconnecter en acceptant `mcp:read` ou `mcp:write` |
| `-32004` | Quota dépassé | Attendre le délai indiqué ; ne jamais boucler |
| `-32603` | Dépendance indisponible | Réessayer plus tard ; ne pas rejouer une écriture sans vérifier |

Sur les routes REST `/api/mcp/v1/*`, les mêmes situations sont des codes HTTP : `400 invalid_arguments` / `invalid_cursor`, `401 unauthenticated`, `403 insufficient_scope` / `access_denied` / `user_required` / `organization_required` / `role_denied`, `404 not_found`, `409 conflict`, `429 quota_exceeded` (avec `Retry-After` quand il est connu), `503 unavailable`, `504 timeout`. Le corps porte `error.code`, `error.message`, `error.retry_after_seconds` et `api_contract_version`.

⚠ Un message d'erreur n'est jamais une donnée : ne pas le recopier comme un fait, et ne pas inventer un identifiant ou une URL qu'il ne contient pas.

## Quotas

Un appel compte pour **une unité** dans les deux compteurs d'appels, partagés entre le connecteur MCP et les routes REST :

| Compteur | Compte gratuit | Abonné | Accès interne |
|---|---|---|---|
| Appels / 24 h glissantes | 100 | 5000 | illimité |
| Appels / 60 s (anti-rafale) | 5 | 30 | illimité |
| Dossiers distincts / jour civil (Paris) | 5 | 500 | illimité |

Cet outil consomme **en plus une unité de dossier** : un dossier vaut une unité pour la journée, quel que soit le nombre de pièces lues ou téléchargées dedans. Le compteur de dossiers repart à minuit, heure de Paris ; les deux compteurs d'appels, eux, glissent sur leur fenêtre.

**Aucun outil n'est réservé à une offre** (décision du 2026-09-17) : un compte gratuit voit et appelle le catalogue entier, ce sont ces plafonds qui bornent son usage.

## Voir aussi

[Référence technique](/docs/reference/concepts.md) · [Tous les outils](/docs/api/index.md) · [OpenAPI](/openapi.json) · [Texte pour agents](/llms-full.txt)
