API B2B HandiRepère
# Guide développeur — API B2B HandiRepère
## 1. Obtenir une clé
1. Connectez-vous à HandiRepère (compte ADMIN de votre organisation lieux).
2. Ouvrez l’organisation → **API / Intégrations**.
3. Créez un **client API**, puis une **clé**.
4. Copiez le secret affiché **une seule fois** (`hr_live_<préfixe>_<secret>`).
## 2. Premier appel
```http
GET /api/v1/b2b/places?q=lyon&limit=10
Authorization: Bearer hr_live_xxxxxxxx_yyyyyyyyyyyyyyyyyyyyyyyy
Accept: application/json
```
Réponse enveloppe :
```json
{
"api_version": "2026-09-28",
"data_generated_at": "…",
"data": { "items": [], "next_cursor": null, "has_more": false }
}
```
## 3. Scopes
| Scope | Usage |
|-------|--------|
| `places:read` | Recherche / détail lieux |
| `territories:read` | Territoires, stats, couverture |
| `trust:read` | Faits + confiance sur détail lieu |
| `incidents:read` | Incidents actifs |
| `compatibility:evaluate` | POST évaluation compatibilité |
Sans le scope requis → **403**.
## 4. Quotas
Profils : `DEVELOPMENT`, `STANDARD`, `HIGH_VOLUME` (limites configurables côté serveur).
Dépassement → **429** + `Retry-After`.
Headers utiles : `X-RateLimit-Remaining`, `X-RateLimit-Remaining-Day`.
## 5. Lieux
- `GET /api/v1/b2b/places` — pagination **cursor** (`cursor`, `limit`, `next_cursor`)
- `GET /api/v1/b2b/places/{id}` — détail + provenance / licences sources
## 6. Trust / provenance
Les faits exposent `trust` (`CONFIRMED` | `PROBABLE` | `STALE` | `CONFLICTING` | `UNKNOWN`) **sans promotion**.
`UNKNOWN` ≠ accessible. `PROBABLE` ≠ `CONFIRMED`.
## 7. Territoires
- `GET /api/v1/b2b/territories/search?q=`
- `GET /api/v1/b2b/territories/{type}/{code}`
- `GET /api/v1/b2b/territories/{type}/{code}/stats`
- `GET /api/v1/b2b/territories/{type}/{code}/places`
- `GET /api/v1/b2b/territories/coverage?level=department|region`
### Cache (stats / coverage)
| `cache.cache_status` | Signification |
|----------------------|---------------|
| `fresh` | Entrée dans le TTL (~15 min) |
| `stale` | TTL dépassé ; payload **servi immédiatement** avec `data_generated_at` réel ; refresh asynchrone (`revalidating=true`) |
| `miss` | Aucune entrée utilisable → calcul synchrone (rare après warm) |
`data_generated_at` / `cache.generated_at` = horodatage **réel** de génération du payload (jamais réécrit pour faire croire un refresh).
### Coverage lite (B2B)
Le mode commercial est **lite** (`mode: "lite"`, `trust_metrics_available: false`) :
pas de jointure `place_fact_trust` (trop coûteuse).
| Champ | Lite | Full (interne) |
|-------|------|----------------|
| `resolved_places` | compté | compté |
| `unknown_facts` / `stale_facts` / `conflicting_facts` | **`null`** | entier (≥0) |
**Règle** : métrique non calculée ≠ `0`. Un `0` n’est autorisé que si `trust_metrics_available=true`.
Disclaimer : `coverage_reflects_handirepere_documented_places_only`.
## 8. Erreurs
| HTTP | Code typique |
|------|----------------|
| 401 | Clé absente / inconnue / révoquée / expirée |
| 403 | Scope manquant / client suspendu |
| 404 | Ressource absente |
| 429 | Quota |
## 9. Staging vs production — auth
**Production (partenaire)** : une seule en-tête
```http
Authorization: Bearer hr_live_<prefix>_<secret>
```
**Staging HandiRepère** : le reverse-proxy / edge exige **en plus** une Basic Auth
d’accès au site de préproduction (`STAGING_BASIC_AUTH_*`). C’est une **protection
d’environnement**, pas une seconde authentification B2B. Après le Basic edge, la clé
API reste Bearer (ou `X-Api-Key` si un client HTTP refuse deux schémas `Authorization`).
Le design production B2B **n’impose pas** de Basic HandiRepère aux partenaires.
## 10. Conditions de réutilisation
Respectez les `licence_identifier` / `attribution_text` des sources dans `provenance`.
HandiRepère ne certifie pas l’accessibilité d’un établissement.
## 11. Spec OpenAPI
Voir `docs/openapi/b2b-v1.yaml`.