# GET /export

> Version générique : tous les champs sont listés avec la formule minimale qui y donne accès (`FREE`, `PRO`, `PARTNER`). Envoyez votre clé API (`Authorization: Bearer th_live_…`) ou connectez-vous à votre espace développeur pour obtenir la version personnalisée.

`GET https://trailhorizon.fr/api/v1/export`

> Endpoint réservé aux formules `PARTNER`. Un compte qui n'y a pas droit reçoit `403 forbidden`.

Catalogue complet en un seul document JSON. Le document est envoyé en flux : lisez-le en continu plutôt que de le charger en mémoire.

Le nombre d'exports est limité par jour (selon la formule). Un export compte aussi pour une requête dans votre quota journalier.

L'export n'est pas disponible avec une clé de test (`th_test_`) : l'appel est refusé en `403 forbidden` et n'entame pas votre allocation d'export. Utilisez une clé de production, depuis un de vos domaines autorisés.

Si le flux échoue côté Trail Horizon (erreur interne en cours d'envoi), l'export est **remboursé** : il ne compte plus dans votre allocation journalière et vous pouvez le relancer. Si vous coupez vous-même la connexion, il reste décompté.

## Réponse `200`

En-tête `Content-Type: application/json; charset=utf-8`.

```json
{
  "generatedAt": "2026-10-27T12:00:00.000Z",
  "data": [
    {
      "id": "clx1a2b3c0000abcd1234efgh",
      "slug": "trail-des-cretes-fictives",
      "name": "Trail des Crêtes Fictives",
      "url": "https://trailhorizon.fr/races/europe/france/auvergne-rhone-alpes/trail-des-cretes-fictives?utm_source=partner-votre-slug&utm_medium=api&utm_campaign=race-data",
      "nextEditionDate": "2027-06-12T00:00:00.000Z",
      "lastEditionDate": "2026-06-13T00:00:00.000Z",
      "firstEditionDate": "2019-06-15T00:00:00.000Z",
      "updatedAt": "2026-10-20T08:30:00.000Z",
      "status": "ACTIVE",
      "verifiedAt": "2026-10-15T10:00:00.000Z",
      "averageRating": 4.5,
      "location": {
        "city": "Exempleville",
        "lat": 45.1234,
        "lon": 6.5678,
        "region": "Auvergne-Rhône-Alpes",
        "country": "France",
        "continent": "Europe"
      },
      "links": {
        "website": "https://exemple.org/trail",
        "registration": "https://exemple.org/trail/inscriptions",
        "facebook": "https://facebook.com/exemple-trail",
        "instagram": "https://instagram.com/exemple_trail",
        "youtube": null
      },
      "images": {
        "logo": "https://files.example.com/trail-des-cretes/logo.png",
        "card": "https://files.example.com/trail-des-cretes/card.jpg",
        "coverDesktop": "https://files.example.com/trail-des-cretes/cover-desktop.jpg",
        "coverPhone": "https://files.example.com/trail-des-cretes/cover-phone.jpg"
      },
      "formats": [
        {
          "id": "clx9z8y7x0001abcd5678ijkl",
          "name": "Le Grand Tour",
          "type": "STANDARD",
          "distance": 52.4,
          "elevation": 3100,
          "category": "50K",
          "price": 85,
          "currency": "EUR",
          "startAt": "2027-06-12T05:00:00.000Z",
          "hasStartTime": true,
          "timezone": "Europe/Paris",
          "duration": null,
          "traceUrl": "https://tracedetrail.fr/trace/0000",
          "registrationStatus": "NOT_YET_OPEN",
          "registrationOpensAt": "2027-01-15T08:00:00.000Z",
          "maxParticipants": 800,
          "practicalInfo": "Matériel obligatoire : Veste imperméable, EMERGENCY_BLANKET\nDépart : Place du village\nArrivée : Place du village\nTemps limite : 14 h 0 min\nRavitaillements : Col des Exemples (km 18)",
          "practicalInfoStructured": {
            "requiredGear": [
              {
                "code": "WATERPROOF_JACKET",
                "label": null,
                "quantity": null
              },
              {
                "code": "EMERGENCY_BLANKET",
                "label": null,
                "quantity": null
              }
            ],
            "recommendedGear": [],
            "start": {
              "location": "Place du village",
              "details": null
            },
            "finish": {
              "location": "Place du village",
              "details": null
            },
            "access": null,
            "timeLimit": {
              "totalMinutes": 840,
              "cutoffs": []
            },
            "aidStations": [
              {
                "name": "Col des Exemples",
                "km": 18,
                "kind": "FULL"
              }
            ],
            "kidsAgeRange": null,
            "relay": null,
            "stageRace": null,
            "notes": null
          },
          "rankingTypes": [
            "ITRA"
          ],
          "tags": [
            "panoramique",
            "technique"
          ]
        },
        {
          "id": "clx9z8y7x0002abcd5678mnop",
          "name": "La Petite Boucle",
          "type": "STANDARD",
          "distance": 21.2,
          "elevation": 1100,
          "category": "20K",
          "price": 38,
          "currency": "EUR",
          "startAt": "2027-06-12T08:30:00.000Z",
          "hasStartTime": true,
          "timezone": "Europe/Paris",
          "duration": null,
          "traceUrl": null,
          "registrationStatus": "NOT_YET_OPEN",
          "registrationOpensAt": "2027-01-15T08:00:00.000Z",
          "maxParticipants": 400,
          "practicalInfo": null,
          "practicalInfoStructured": null,
          "rankingTypes": [],
          "tags": []
        }
      ]
    }
  ],
  "count": 1
}
```

## Exemple

```bash
curl -H "Authorization: Bearer th_live_VOTRE_CLE" \
  -H "X-TrailHorizon-Origin: votre-domaine.fr" \
  "https://trailhorizon.fr/api/v1/export"
```

## Erreurs

| Statut | Code | Signification |
| --- | --- | --- |
| 401 | `missing_api_key` | Header `Authorization` absent. |
| 401 | `invalid_api_key` | Clé mal formée ou inconnue. |
| 401 | `api_key_revoked` | Clé révoquée. |
| 403 | `account_suspended` / `account_revoked` | Compte suspendu ou révoqué. |
| 403 | `tos_not_accepted` | Conditions d'utilisation de l'API jamais acceptées (refus immédiat). |
| 403 | `tos_outdated` | Nouvelle version des conditions non acceptée dans le délai de grâce. |
| 403 | `origin_required` | Header `X-TrailHorizon-Origin` absent. Voir [Domaines autorisés](domains.md). |
| 403 | `origin_not_allowed` | Origine invalide, ou qui ne correspond à aucun domaine autorisé rattaché à la clé. |
| 403 | `origin_suspended` | Domaine suspendu (au-delà de la limite de votre formule) ou déclaré Non conforme après revue. |
| 403 | `forbidden` | L'export complet n'est pas disponible pour votre formule, ou l'appel utilise une clé de test. |
| 429 | `rate_limit_exceeded` | Trop de requêtes dans la minute. Voir `Retry-After`. |
| 429 | `daily_quota_exceeded` | Quota journalier atteint. Voir `Retry-After`. |
| 429 | `export_quota_exceeded` | Nombre d'exports journaliers atteint. Voir `Retry-After`. |
| 500 | `internal_error` | Erreur interne. |
