> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.client-p.pylote.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Guide d'intégration

> Stratégie de synchronisation, pagination et gestion des profils supprimés

## Stratégie de synchronisation

La méthode recommandée pour synchroniser les freelances Pylote dans votre base :

### Synchronisation initiale

Utilisez `modifiedTime=0` pour récupérer **tous** les freelances, puis paginez :

```javascript theme={null}
const axios = require('axios');

async function syncAllFreelances() {
  const API_URL = 'https://client-p.pylote.io/freelances';
  const API_KEY = process.env.PYLOTE_API_KEY;
  const limit = 1000;
  let page = 1;
  let totalPages = 1;
  let allFreelances = [];

  while (page <= totalPages) {
    const response = await axios.get(API_URL, {
      headers: { 'x-api-key': API_KEY },
      params: { modifiedTime: 0, page, limit, showDeleted: false }
    });

    allFreelances.push(...response.data.freelances);
    totalPages = response.data.infos.totalPages;
    page++;
  }

  console.log(`${allFreelances.length} freelances synchronisés`);
  return allFreelances;
}
```

### Synchronisation incrémentale

Stockez le timestamp de votre dernière synchronisation, puis récupérez uniquement
les profils modifiés depuis :

```javascript theme={null}
async function syncUpdatedFreelances(lastSyncTimestamp) {
  const response = await axios.get(API_URL, {
    headers: { 'x-api-key': API_KEY },
    params: {
      modifiedTime: lastSyncTimestamp,  // Unix timestamp en secondes
      page: 1,
      limit: 1000,
      showDeleted: true  // inclure les profils supprimés
    }
  });

  for (const freelance of response.data.freelances) {
    if (freelance.meta.status === 'deleted') {
      // OBLIGATOIRE : supprimer de votre base
      await deleteFromYourDB(freelance.meta.id);
    } else {
      await upsertInYourDB(freelance);
    }
  }

  // Stocker le nouveau timestamp pour le prochain sync
  return Math.floor(Date.now() / 1000);
}
```

<Warning>
  Les freelances avec `status: deleted` **doivent être supprimés** de votre base
  dans un délai de 30 jours. C'est un engagement contractuel.
  Les statuts de suppression possibles sont :
  `account_deleted`, `account_banned`, `account_excluded`, `account_invisible`.
</Warning>

## Pagination

Les réponses sont paginées avec les paramètres `page` et `limit`.
Chaque réponse inclut un objet `infos` :

```json theme={null}
{
  "freelances": [...],
  "infos": {
    "total": 1234,
    "page": 1,
    "limit": 50,
    "totalPages": 25
  }
}
```

| Paramètre      | Type    | Requis | Description                             |
| -------------- | ------- | ------ | --------------------------------------- |
| `page`         | integer | Oui    | Numéro de page (commence à 1)           |
| `limit`        | integer | Oui    | Freelances par page (max 1000)          |
| `modifiedTime` | integer | Oui    | Timestamp Unix (secondes). `0` = tous   |
| `showDeleted`  | boolean | Non    | Inclure les supprimés (default: `true`) |

<Note>
  Utilisez `limit=1000` pour minimiser le nombre de requêtes.
  Un sync initial de \~22 000 freelances prend environ 22 pages.
</Note>

## Dédoublonnage

Un même freelance peut être présent sur plusieurs plateformes. Le champ `meta.personalEmail`
(hash SHA-256 de l'email personnel) vous permet de dédoublonner :

```javascript theme={null}
// Si deux profils ont le même personalEmail, c'est le même freelance.
// Gardez celui avec le updatedAt le plus récent.
const seen = new Map();
for (const f of freelances) {
  const hash = f.meta.personalEmail;
  if (!seen.has(hash) || f.meta.updatedAt > seen.get(hash).meta.updatedAt) {
    seen.set(hash, f);
  }
}
```

## URLs trackées (hive.pylote.io)

Les champs `basics.url` (LinkedIn) et le lien CV dans `basics.profiles` passent par
le proxy `hive.pylote.io`. Ces URLs :

* **Trackent les consultations** pour les stats du freelance
* **Contiennent un watermark** (IP de l'appelant encodée en base64)
* **Ne doivent pas être partagées** en dehors de votre plateforme

Format :

```
https://hive.pylote.io/linkedin/{id_chiffre}/{clientPk}?t={watermark}
https://hive.pylote.io/cv/{id_chiffre}/{clientPk}?t={watermark}
```

## Récupérer des freelances spécifiques

Si vous avez besoin de re-synchroniser un sous-ensemble de profils
(par exemple après un incident), utilisez `POST /freelances` avec une liste d'IDs :

```bash theme={null}
curl -X POST "https://client-p.pylote.io/freelances?modifiedTime=0&page=1&limit=100" \
  -H "x-api-key: votre-cle" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": [
      "bc1d49cf-1cc7-4afe-92aa-0ebd545fcd12",
      "960a1c67-645d-4ac5-b8b2-875fb2f740d3"
    ]
  }'
```

## Fréquence de synchronisation recommandée

| Stratégie           | Fréquence         | Cas d'usage                              |
| ------------------- | ----------------- | ---------------------------------------- |
| **Cron classique**  | Toutes les heures | Suffisant pour la plupart des clients    |
| **Semi-temps réel** | Toutes les 15 min | Si la fraîcheur de la dispo est critique |
| **Sync initial**    | Une fois          | Premier peuplement de votre base         |

<Info>
  Le cache de l'API est rafraîchi **toutes les heures**. Synchroniser plus souvent
  que toutes les heures n'apporte pas de données supplémentaires.
</Info>
