Tous les endpoints REST de Personyze partagent une syntaxe commune de paramètres de chemin pour filtrer, sélectionner des colonnes, trier et limiter les résultats. Les mêmes modificateurs — where, columns, column, order_by, order_by_desc, limit — fonctionnent de la même façon sur tous les objets, avec une forme abrégée pour les recherches par clé primaire.
Prérequis : Présentation de l’API REST et Authentification — c’est là que sont expliquées la forme de l’URL et les identifiants.
Forme générale de l’URL
Après le nom de l’objet, le chemin de l’URL est une suite de paires /<modifier>/<value>/... :
/rest/<object>/[<id>|]<modifier>/<value>/<modifier>/<value>/...
Remarques :
- L’ordre n’a pas d’importance.
/limit/100/where/x=yéquivaut à/where/x=y/limit/100. - Chaque modificateur apparaît au plus une fois par requête. Plusieurs conditions
wherese placent dans un seul segmentwhere/à l’aide des opérateurs&et|(voir ci-dessous). - Les valeurs sont décodées (URL-decoded) avant l’analyse — une valeur de colonne contenant
/,=,&, ou%doit donc être encodée en pourcentage.
Forme à ID unique (recherche par clé primaire)
Un segment numérique seul en première position est une recherche par clé primaire :
GET /rest/<object>/<id>
Cela renvoie un seul enregistrement (un objet, pas un tableau à un élément), ou 400 Row not found si l’ID n’existe pas.
GET /rest/placeholders/14
GET /rest/users/57291 # PK = user_id
Pour les recherches par identifiant externe (votre SKU, votre ID CRM, etc.), utilisez la forme where avec internal_id:
GET /rest/users/where/internal_id=42
GET /rest/products/where/internal_id=SKU-1234
where — filtrage
Filtre l’ensemble des résultats. La forme la plus simple est where/<column><op><value>:
| Opérateur | Signification | Exemple |
|---|---|---|
= |
égal à | where/status=active |
!= |
différent de | where/status!=draft |
> |
supérieur à | where/last_session_time>1700000000 |
>= |
supérieur ou égal à | where/age_from>=18 |
< |
inférieur à | where/time<1700000000 |
<= |
inférieur ou égal à | where/age_to<=65 |
: |
dans (liste séparée par des virgules) | where/id:1,2,3,4 |
!: |
pas dans | where/status!:draft,archived |
Combiner des conditions avec & (ET) et | (OU)
where/<cond1>&<cond2> # both must match (AND)
where/<cond1>|<cond2> # either matches (OR)
where/<a>&<b>|<c>&<d> # (a AND b) OR (c AND d) — & binds tighter than |
Exemples :
where/status=active&age_from>=18
where/email=alice@example.com|email=bob@example.com
where/category:books,tools&is_in_stock=yes
Exigence de colonne indexée
Les endpoints REST qui couvrent de grandes tables (users, events, sessions_archive, summary_actions, etc.) rejettent les requêtes dont le where ou le order_by ne s’appuie pas sur un index. Le message d’erreur nomme les colonnes indexées exposées par l’endpoint :
Cannot do this operation on whole table: column "uset_id" is not indexed.
Please, use "where" condition or order by an indexed column
(user_id, last_session_time, data_last_modified, fb_id, email, internal_id).
Les index composites apparaissent sous la forme [col1, col2, col3] . Seule la colonne de tête d’un composite peut servir de filtre sur une seule colonne :
... or order by an indexed column
(user_id, [product_internal_id, user_id, transaction_time], status, time).
Ici, where/product_internal_id=... s’appuie sur l’index composite, mais where/transaction_time>... seul ne le fait pas — c’est la troisième colonne du composite, utile uniquement en combinaison avec product_internal_id et user_id.
columns — sélectionner des colonnes précises
Restreint les colonnes renvoyées. Liste séparée par des virgules. Par défaut : « toutes les colonnes documentées » de l’objet.
GET /rest/users/where/internal_id=42/columns/user_id,first_name,last_name
Colonnes inconnues : pour les objets qui acceptent des noms de colonnes dynamiques (users, articles, products), les colonnes inconnues sont renvoyées à null. Pour les objets à schéma fixe, vous obtiendrez 400 Unknown column.
column (au singulier) — tableau plat de valeurs
Raccourci pour « sélectionner une colonne et renvoyer un tableau plat de valeurs » au lieu d’un tableau d’objets.
GET /rest/users/where/last_session_time>1700000000/column/email
→ ["alice@example.com", "bob@example.com", ...]
Par rapport à la forme plurielle columns :
GET /rest/users/where/last_session_time>1700000000/columns/email
→ [{"email":"alice@example.com"}, {"email":"bob@example.com"}, ...]
Utile quand vous voulez transmettre directement le résultat à un autre système qui attend une liste (par ex. pour construire un export d’audience ou dédoublonner des adresses e-mail).
order_by / order_by_desc
order_by/<col>[,<col>...] # ascending
order_by_desc/<col>[,<col>...] # descending
Plusieurs colonnes : les égalités sur la première colonne sont départagées par la deuxième, et ainsi de suite. Chaque sens (order_by ou order_by_desc) s’applique à toutes les colonnes listées.
GET /rest/users/order_by_desc/last_session_time/limit/100
La première colonne listée doit être une colonne indexée (ou la colonne de tête d’un index composite) en l’absence de clause where — sinon l’endpoint rejette la requête comme un parcours complet de table.
limit — pagination
limit/<count> # first <count> rows
limit/<offset>,<count> # skip <offset> then take <count>
La limite stricte est de 1 000 lignes par requête. Les valeurs plus grandes sont rejetées avec 400 Only can select up to 1000 rows.
GET /rest/users/order_by_desc/last_session_time/limit/100
GET /rest/users/order_by_desc/last_session_time/limit/100,100 # rows 100..199
Pagination par curseur — à privilégier pour les grands ensembles de résultats
Les valeurs offset profondes deviennent lentes, car la base de données doit relire toutes les lignes sautées. Pour les grands ensembles de résultats, paginez en parcourant la colonne indexée order_by avec des conditions de type curseur where:
# page 1
GET /rest/users/order_by_desc/last_session_time/limit/1000
# page 2 — pass the last seen value
GET /rest/users/where/last_session_time<1730000000/order_by_desc/last_session_time/limit/1000
# page 3 — pass the last seen value from page 2
GET /rest/users/where/last_session_time<1729000000/order_by_desc/last_session_time/limit/1000
La valeur du curseur est celle qu’avait, pour la colonne indexée, le dernier enregistrement de la page précédente. Cela reste rapide indéfiniment — chaque page est un parcours de plage indexé, pas un parcours linéaire du type « sauter 50 000 lignes ».
< et non <=) plus un critère de départage sur une colonne unique — par ex. where/last_session_time<X&user_id<Y.Tout assembler
GET /rest/products
/where/category=tools&is_in_stock=yes
/columns/id,internal_id,title,price,inventory
/order_by/title
/limit/100
(Retours à la ligne ajoutés pour la lisibilité — en réalité, tout tient sur une seule ligne, sans espaces.)