# Documentation de l'API (Bêta)

Utilisez l'API RandomCoffee pour créer des attributs, importer des utilisateurs et consulter leurs données de participation.

import { Badge } from '@prosefly/astro-components';
import Callout from '@components/Callout.astro';

<Callout type="note">
  Notre API est actuellement en bêta et nous l'améliorons en continu. Pour toute question, demande de fonctionnalité ou suggestion d'amélioration, n'hésitez pas à nous écrire. Vos retours nous aident à rendre l'API meilleure pour tout le monde !
</Callout>

## Prérequis

- Un espace de travail **RandomCoffee** avec le **plan Enterprise**

### URL de base

```text
https://api.random-coffee.com/api/v2
```

### Authentification

Tous les endpoints nécessitent un jeton d'API pour l'authentification. Le jeton doit être transmis dans l'en-tête `Authorization` avec le schéma `Bearer`.

Exemple :

```text
Authorization: Bearer YOUR_API_TOKEN
```

### 1. Créer une catégorie / un attribut

### <Badge color="success">POST</Badge> `/data/attributes/`

Crée une nouvelle catégorie ou un nouvel attribut pour votre entreprise.

**Corps de la requête :**

```json
{
    "title": "Location",
    "description": "User's workplace location",
    "type": "select",
    "values": ["New York", "San Francisco", "Chicago"]
}
```

**Paramètres du corps de la requête :**

- `title` (string, obligatoire) : le nom de la catégorie ou de l'attribut (par exemple, "Location").
- `description` (string, obligatoire) : une description de la catégorie ou de l'attribut (par exemple, "User's workplace location").
- `type` (string, facultatif) : le type de la catégorie. Valeurs possibles : `"select"` , `"text"` , `"date"`, `"integer"` ,`"array"` ou `"boolean"`. Par défaut : `"select"`.
- `values` (array, facultatif) : une liste de valeurs prédéfinies pour la catégorie. Uniquement si le `type` est `"select"` ou `"array"`.

**Réponse :**

- Code de statut HTTP : `201 OK` en cas de succès.
- Renvoie le détail de la catégorie ou de l'attribut créé.

```json
{
    "id": 1,
    "title": "Location",
    "description": "User's workplace location",
    "type": "select",
    "values": ["New York", "San Francisco", "Chicago"],
    "created_at": "2025-01-14T00:00:00Z"
}
```

### 2. Récupérer les catégories / attributs

### <Badge color="info">GET</Badge> `/data/attributes/`

Récupère la liste de toutes les catégories et de tous les attributs de votre entreprise.

**Réponse :**

- Code de statut HTTP : `200 OK` en cas de succès.
- Renvoie une liste de catégories et d'attributs.

```json
[
    {
        "id": 1,
        "title": "Location",
        "description": "User's workplace location",
        "type": "select",
        "values": ["New York", "San Francisco", "Chicago"],
        "created_at": "2025-01-14T00:00:00Z"
    },
    {
        "id": 2,
        "title": "Department",
        "description": "User's department",
        "type": "text",
        "values": [],
        "created_at": "2025-01-14T00:00:00Z"
    }
]
```

### 3. Importer des utilisateurs

### <Badge color="success">POST</Badge> `/data/uploads/`

Importe une liste d'utilisateurs en masse, avec leurs attributs.

**Corps de la requête :**

```json
{
    "users": [
        {
            "first_name": "John",
            "last_name": "Doe",
            "email": "john.doe@example.com",
            "extra_data": {
                "Location": "New York",
                "Department": "Engineering"
            }
        },
        {
            "first_name": "Jane",
            "last_name": "Doe",
            "email": "jane.doe@example.com",
            "extra_data": {
                "Location": "San Francisco",
                "Department": "Marketing"
            }
        }
    ]
}
```

**Paramètres du corps de la requête :**

- `users` (array, obligatoire) : la liste des utilisateurs à importer. Chaque utilisateur doit avoir :
  - `first_name` (string, obligatoire)
  - `last_name` (string, obligatoire)
  - `email` (string, obligatoire)
  - `extra_data` (object, facultatif) : les attributs personnalisés et leurs valeurs (par exemple, `"Location": "New York"`).

**Réponse :**

- Code de statut HTTP : `201 OK` en cas de succès.
- Renvoie le détail de l'import.

```json
{
    "id": 123,
    "finished_processing_at": null,
    "results": {"errors": [], "users": {}},
    "created_at": "2025-01-14T00:00:00Z"
}
```

---

### 4. Récupérer le détail d'un import

### <Badge color="info">GET</Badge> `/data/uploads/{upload_id}/`

Récupère le détail d'un import à partir de son identifiant.

**Paramètres d'URL :**

- `upload_id` (integer, obligatoire) : l'identifiant de l'import.

**Réponse :**

- Code de statut HTTP : `200 OK` en cas de succès.
- Renvoie le détail de l'import, avec les résultats du traitement.

```json
{
    "id": 123,
    "finished_processing_at": null,
    "results": {"errors": [], "users": {}},
    "created_at": "2025-01-14T00:00:00Z"
}
```

### 5. Récupérer le détail d'un utilisateur

### <Badge color="info">GET</Badge> `/data/users/{email}/`

Récupère les informations détaillées d'un utilisateur, identifié par son adresse email.

**Paramètres d'URL :**

- `email` (string, obligatoire) : l'adresse email de l'utilisateur.

**Réponse :**

- Code de statut HTTP : `200 OK` en cas de succès.
- Renvoie un objet JSON avec les informations de l'utilisateur et ses indicateurs de participation.

```json
{
    "email": "thierry.john@company.com",
    "first_name": "Thierry",
    "last_name": "John",
    "is_active": true,
    "randomcoffee_count": 13,
    "last_randomcoffee_date": "2025-06-10T09:30:00Z"
}
```

### 6. Récupérer la liste des utilisateurs

Cet endpoint permet de récupérer la liste des utilisateurs de votre organisation.

### <Badge color="info">GET</Badge> `/data/users/`

L'endpoint `Get Users List` renvoie une liste paginée d'utilisateurs, avec leurs indicateurs de participation.

Vous pouvez choisir le nombre d'utilisateurs renvoyés par page avec le paramètre `limit`, et parcourir toutes les pages grâce à la valeur `next` fournie dans la réponse.

Vous pouvez aussi appliquer des **filtres** pour ne récupérer que les utilisateurs qui répondent à certains critères (par exemple, uniquement les utilisateurs actifs).

**Réponse :**

- Code de statut HTTP : `200 OK` en cas de succès.
- Renvoie un objet JSON avec les informations de pagination et le détail des utilisateurs.

```json
{
    "count": 1,
    "next": null,
    "previous": null,
    "offset_start": 1,
    "offset_end": 1,
    "results": [
        {
            "email": "thierry.john@company.com",
            "first_name": "Thierry",
            "last_name": "John",
            "is_active": true,
            "randomcoffee_count": 13,
            "last_randomcoffee_date": "2025-06-10T09:30:00Z"
        }
    ]
}
```

**Pagination**

Les résultats sont **paginés** pour de meilleures performances.

Chaque réponse contient :

- `results` : la liste des utilisateurs de la page en cours
- `next` : l'URL de la page de résultats suivante (ou `null` s'il n'y a plus de résultats)
- `previous` : l'URL de la page de résultats précédente (ou `null`)

Vous pouvez utiliser le paramètre `limit` pour définir le nombre maximum d'utilisateurs par page (par défaut : 10).

**Exemple de parcours des pages :**

1. Appelez l'endpoint avec `?limit=50`
2. Lisez la réponse et récupérez `results`
3. Si le champ `next` n'est pas null, appelez l'URL suivante
4. Continuez jusqu'à ce que `next` soit null

**Filtres**

Vous pouvez filtrer la liste des utilisateurs en passant un paramètre `filters` sous forme de chaîne JSON.

Les filtres suivent un schéma structuré qui prend en charge :

- **version** : la version du schéma de filtre (actuellement `"v1"`)
- **operator** : l'opérateur logique (`"and"` ou `"or"`)
- **filters** : la liste des conditions, avec :
  - `type` : le champ sur lequel filtrer (par exemple, `is_active`, `email`, `first_name`, `last_name`)
  - `operator` : l'opérateur de comparaison (`eq`, `ne`, `in`, etc.)
  - `value` : la ou les valeurs à comparer

### Exemple d'objet de filtre

```json
{
  "version": "v1",
  "operator": "or",
  "filters": [
    { "type": "is_active", "operator": "eq", "value": 1 }
  ]
}
```

Ce filtre ne récupère que les utilisateurs **actifs** (`is_active = 1`).

---

### Exemple : récupérer tous les utilisateurs actifs (en Python)

```python
import requests
import json

BASE_API_URL = "https://api.random-coffee.com/api/v2"

def get_users(filters=None):
    url = f"{BASE_API_URL}/data/users/?limit=50"
    if filters:
        url += f"&filters={filters}"
    data = []
    while url:
        resp = requests.get(url, headers={
            "Authorization": "Bearer {{KEY}}"
        }).json()
        data.extend(resp["results"])
        url = resp["next"]
    return data

# Define filter for active users
filters = json.dumps({
    "version": "v1",
    "operator": "or",
    "filters": [{"type": "is_active", "operator": "eq", "value": 1}]
})

active_users = get_users(filters=filters)
```

### Exemple : récupérer les utilisateurs inactifs

```python
inactive_filters = json.dumps({
    "version": "v1",
    "operator": "or",
    "filters": [{"type": "is_active", "operator": "eq", "value": 0}]
})

inactive_users = get_users(filters=inactive_filters)
```

### Exemple : récupérer les utilisateurs selon la date de leur dernier RandomCoffee

```python
by_last_randomcoffee_date_filters = json.dumps({
    'version': 'v1',
    'operator': 'or',
    'filters': [{
        'value': '2025-09-10',
        'operator': 'gte',
        'type': 'last_randomcoffee_date'
    }]
})

users = get_users(filters=by_last_randomcoffee_date_filters)
```

### Gestion des erreurs

- `401 Unauthorized` : jeton d'authentification absent ou invalide.
- `403 Forbidden` : jeton invalide ou droits insuffisants.
- `400 Bad Request` : données de requête invalides (par exemple, champs obligatoires manquants).
- `404 Not Found` : ressource introuvable.
- `405 Method Not Allowed` : méthode HTTP non valide pour cette ressource.

### Limite de requêtes

Le nombre de requêtes vers cette API est limité pour éviter les abus. Pensez à gérer le statut `429 Too Many Requests` en relançant la requête après le délai indiqué.

### Exemples de tests

Voici quelques cas de test pour ces routes :

### Cas de test 1 : créer une catégorie

```python
import requests

BASE_API_URL = "https://api.random-coffee.com/api/v2"

response = requests.post(f'{BASE_API_URL}/data/attributes/', json={
    "title": "Location",
    "description": "User's workplace location",
    "type": "select",
    "values": ["New York", "San Francisco"]
}, headers={"Authorization": "Bearer YOUR_API_TOKEN"})
assert response.status_code == 201
assert response.json()['title'] == "Location"
```

### Cas de test 2 : importer des utilisateurs

```python
import requests

BASE_API_URL = "https://api.random-coffee.com/api/v2"

response = requests.post(f'{BASE_API_URL}/data/uploads/', json={
    "users": [
        {
            "first_name": "John",
            "last_name": "Doe",
            "email": "john.doe@example.com",
            "extra_data": {"Location": "New York"}
        },
        {
            "first_name": "Jane",
            "last_name": "Doe",
            "email": "jane.doe@example.com",
            "extra_data": {"Location": "San Francisco"}
        }
    ]
}, headers={"Authorization": "Bearer YOUR_API_TOKEN"})
assert response.status_code == 201
```

### Cas de test 3 : récupérer le détail d'un import

```python
import requests

BASE_API_URL = "https://api.random-coffee.com/api/v2"

response = requests.get(
    f'{BASE_API_URL}/data/uploads/123/',
    headers={"Authorization": "Bearer YOUR_API_TOKEN"}
)
assert response.status_code == 200
assert response.json()['id'] == 123
```
