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

# Télécharger l'avis AADL

> Téléchargez l'avis de paiement officiel d'AADL pour l'une de vos propres transactions

## Vue d'ensemble

Diffuse l'*avis de paiement* qu'`AADL` publie pour un dossier de logement — le PDF que le locataire téléchargerait lui-même chez le facturier — pour une transaction qui vous appartient. Comme [Télécharger le reçu](/fr/api-reference/bill-payment/get-receipt), cet endpoint ne renvoie pas l'enveloppe JSON en cas de succès : le corps, ce sont les octets, que vous pouvez transmettre directement à votre propre client.

Ce n'est pas le reçu. Le reçu prouve que votre paiement est passé ; l'avis est l'état que publie AADL pour le dossier. Seul `AADL` en produit un.

<Warning>
  **L'avis s'adresse par transaction, jamais par dossier de logement.** Cette requête ne contient aucun `codeloc`, et aucun n'est accepté. Nous chargeons la transaction, vérifions qu'elle est bien la vôtre dans cet environnement, la refusons si son `partner` n'est pas `AADL`, puis lisons le dossier de logement dans la facture déjà enregistrée sur cette transaction.

  C'est délibéré. La page d'export d'AADL ne demande aucune session et renvoie un PDF pour n'importe quel code, existant ou non : relayer un code fourni par l'appelant transformerait cet endpoint en outil d'énumération des dossiers d'autrui. Le résoudre depuis votre propre transaction rend cela impossible.
</Warning>

## Paramètres de chemin

<ParamField path="transactionId" type="string" required>
  L'identifiant de transaction. Une chaîne hexadécimale minuscule de 24 caractères, issue de [Obtenir une transaction par ID](/fr/api-reference/bill-payment/check-by-id) ou de n'importe quelle liste, appartenant à l'une de vos transactions `AADL`.

  Contrairement au reçu, la transaction n'a pas besoin d'être en `SUCCESS` : n'importe laquelle de vos transactions `AADL` ayant résolu une facture peut produire un avis.
</ParamField>

## Réponse

En cas de succès, le corps est le PDF lui-même. Lisez les en-têtes pour savoir ce que vous avez reçu.

<ResponseField name="Content-Type" type="header" required>
  `application/pdf`.
</ResponseField>

<ResponseField name="Content-Disposition" type="header" required>
  `attachment; filename="avis_<transactionId>.pdf"`. Le nom est construit à partir du seul identifiant de transaction : il ne porte aucune identité de locataire.
</ResponseField>

<ResponseField name="Content-Length" type="header" required>
  La taille du fichier en octets.
</ResponseField>

<ResponseField name="Cache-Control" type="header" required>
  `private, no-store`. AADL régénère l'avis à la demande et le remplace à chaque période : il n'y a rien de stable à mettre en cache — et c'est le document d'un client, jamais un document partagé.
</ResponseField>

## Exemples

<CodeGroup>
  ```bash cURL theme={null}
  # -J -O écrit le fichier sous le nom proposé par le serveur
  curl https://api.oneclickdz.com/v3/bills/transactions/68b2f4c1a7d3e9f204c81a55/avis \
    -H "X-Access-Token: YOUR_API_KEY" \
    --fail \
    --remote-header-name --remote-name
  ```

  ```javascript Node.js theme={null}
  import { writeFile } from "node:fs/promises";

  const transactionId = "68b2f4c1a7d3e9f204c81a55";

  const response = await fetch(
    `https://api.oneclickdz.com/v3/bills/transactions/${transactionId}/avis`,
    { headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY } },
  );

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`${error.error.code}: ${error.error.message}`);
  }

  const bytes = Buffer.from(await response.arrayBuffer());
  await writeFile(`avis-${transactionId}.pdf`, bytes);

  console.log(bytes.length);
  ```

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

  transaction_id = '68b2f4c1a7d3e9f204c81a55'

  response = requests.get(
      f'https://api.oneclickdz.com/v3/bills/transactions/{transaction_id}/avis',
      headers={'X-Access-Token': os.getenv('ONECLICKDZ_API_KEY')}
  )

  if response.status_code != 200:
      error = response.json()
      raise RuntimeError(f"{error['error']['code']}: {error['error']['message']}")

  with open(f'avis-{transaction_id}.pdf', 'wb') as handle:
      handle.write(response.content)

  print(len(response.content))
  ```

  ```php PHP theme={null}
  <?php
  $transactionId = '68b2f4c1a7d3e9f204c81a55';

  $ch = curl_init("https://api.oneclickdz.com/v3/bills/transactions/$transactionId/avis");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-Access-Token: ' . getenv('ONECLICKDZ_API_KEY')
  ]);

  $bytes  = curl_exec($ch);
  $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

  if ($status !== 200) {
      $error = json_decode($bytes, true);
      throw new Exception($error['error']['code'] . ': ' . $error['error']['message']);
  }

  file_put_contents("avis-$transactionId.pdf", $bytes);

  echo strlen($bytes);
  ?>
  ```
</CodeGroup>

### Réponse de succès

Le corps est binaire. Les en-têtes ressemblent à ceci :

```http theme={null}
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Length: 71204
Content-Disposition: attachment; filename="avis_68b2f4c1a7d3e9f204c81a55.pdf"
Cache-Control: private, no-store
```

## Réponses d'erreur

Les erreurs sont renvoyées en JSON, dans la même enveloppe que pour tous les autres endpoints.

<AccordionGroup>
  <Accordion title="401 — Jeton d'accès manquant ou invalide">
    **La clé était absente ou a été rejetée.**

    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "INVALID_ACCESS_TOKEN",
        "message": "The provided access token is invalid."
      },
      "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
    }
    ```

    **Que faire :** vérifiez la clé selon le guide [Authentification](/fr/authentication).
  </Accordion>

  <Accordion title="404 — Transaction introuvable">
    **L'identifiant est inconnu, ou la transaction n'est pas la vôtre dans cet environnement.**

    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "NOT_FOUND",
        "message": "Transaction not found."
      },
      "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
    }
    ```

    Une clé sandbox ne voit jamais une transaction de production, et aucune des deux ne voit celle d'une autre clé. La réponse est identique dans tous les cas : l'endpoint ne confirme donc jamais l'existence de la transaction de quelqu'un d'autre.

    **Que faire :** vérifiez l'identifiant, et vérifiez que vous utilisez bien la clé avec laquelle la transaction a été créée.
  </Accordion>

  <Accordion title="404 — Ce n'est pas une transaction AADL">
    **La transaction est bien la vôtre, mais son partenaire ne publie pas d'avis.**

    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "NOT_FOUND",
        "message": "This partner does not publish a downloadable avis."
      },
      "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
    }
    ```

    **Que faire :** lisez d'abord `partner` sur la transaction et ne proposez le téléchargement que lorsqu'il vaut `AADL`. Pour tous les autres facturiers, c'est [le reçu](/fr/api-reference/bill-payment/get-receipt) qu'il vous faut.
  </Accordion>

  <Accordion title="404 — Aucun avis disponible pour l'instant">
    **Aucun dossier de logement n'a encore été résolu sur cette transaction, ou AADL a refusé de produire le document.**

    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "NOT_FOUND",
        "message": "No avis is available for this transaction yet."
      },
      "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
    }
    ```

    Une découverte qui n'a pas encore atteint `READY` ne porte aucune facture : il n'y a donc rien d'où résoudre un dossier de logement.

    **Que faire :** attendez que la transaction porte une facture, puis réessayez. Un refus du facturier mérite un essai supplémentaire, pas une boucle.
  </Accordion>
</AccordionGroup>

## À quoi sert l'avis

<CardGroup cols={2}>
  <Card title="Montrer au client ce qu'il doit" icon="file-invoice">
    L'avis porte le détail établi par AADL pour le dossier de logement. C'est le document que le locataire reconnaît.
  </Card>

  <Card title="Pas un substitut au reçu" icon="receipt">
    Seul [le reçu](/fr/api-reference/bill-payment/get-receipt) prouve qu'un paiement est passé. C'est celui-là qu'il faut conserver avec votre commande.
  </Card>
</CardGroup>

<Note>
  Rappelez-vous qu'un dossier de logement AADL n'a qu'**un seul** avis ouvert, avec ses éventuels arriérés intégrés au total : ce PDF représente donc tout ce que doit le dossier, jamais une période parmi d'autres. Voir [Partenaires et comptes](/fr/bill-payment-guides/1-partners-and-accounts).
</Note>

## Bonnes pratiques

<CardGroup cols={2}>
  <Card title="Vérifiez d'abord le partenaire" icon="building-columns">
    Ne proposez le téléchargement que pour les transactions `AADL`. Tous les autres partenaires répondent `404 NOT_FOUND`.
  </Card>

  <Card title="N'exposez jamais l'URL" icon="shield-halved">
    Cette URL exige votre clé API. Servez les octets depuis votre propre système, derrière votre propre authentification.
  </Card>

  <Card title="Récupérez-le au moment voulu" icon="rotate">
    `no-store` n'est pas décoratif : AADL remplace l'avis à chaque période. Téléchargez-le quand vous en avez besoin.
  </Card>

  <Card title="N'envoyez jamais de codeloc" icon="lock">
    Il n'y a aucun paramètre d'identifiant à deviner. Si votre code en construit un, c'est qu'il appelle autre chose.
  </Card>
</CardGroup>

## Endpoints associés

<CardGroup cols={2}>
  <Card title="Télécharger le reçu" icon="file-arrow-down" href="/fr/api-reference/bill-payment/get-receipt">
    La preuve d'un paiement réussi
  </Card>

  <Card title="Obtenir une transaction par ID" icon="id-card" href="/fr/api-reference/bill-payment/check-by-id">
    Où apparaissent `partner` et les factures
  </Card>

  <Card title="Découvrir les factures" icon="magnifying-glass-dollar" href="/fr/api-reference/bill-payment/discover-bills">
    Comment un dossier de logement AADL est interrogé
  </Card>

  <Card title="Partenaires et comptes" icon="address-card" href="/fr/bill-payment-guides/1-partners-and-accounts">
    Les règles d'identifiant AADL
  </Card>
</CardGroup>
