Ceci est une traduction. La version allemande est celle qui fait foi. En cas de divergence, c’est le texte allemand qui s’applique. Tu peux changer de langue en bas de page.
Sommaire
Vue d’ensemble
v2 est l’API de tellmelo pour tes propres programmes. Chaque requête porte une clé, chaque réponse est du JSON, et chaque liste se feuillette de la même manière. Ce qui se passe derrière une clé traverse les mêmes règles qu’un clic dans l’application : limites de débit, suspensions, droits retirés et réglages de cette instance valent ici pareillement.
Chaque chemin commence par /api/v2 à l’adresse de cette instance, celle des exemples de cette page.
Requêtes et réponses sont en JSON, en UTF-8. Les noms de champs, les codes et les valeurs sont en anglais et le restent.
Une clé agit en tant que ton compte, jamais au-delà : ce que tu ne peux pas voir dans l’application, aucune clé ne peut le lire.
https://tellmelo.com/api/v2
Démarrage rapide
Crée une clé sous « Réglages → App et données → API » et copie-la. Elle n’est montrée qu’une seule fois.
Interroge la racine avec elle. La réponse dit quelle version tourne, ce que la clé peut faire et combien de requêtes il lui reste cette minute.
Ensuite, chaque chemin fonctionne de la même façon : la clé dans l’en-tête, du JSON en retour, et pour les listes items et next.
Pour continuer : /me pour ton propre profil, /posts pour ce qui est public, /feed pour ce que l’application te montre.
Ta clé
Il y a exactement une clé par compte, liée à ton identifiant. Elle commence par tm_key_, pour qu’un scanner la reconnaisse là où elle n’a pas sa place. Elle s’affiche une seule fois, au moment où elle est créée ; ensuite il ne reste ici que son empreinte, et personne ne peut te la relire, ni nous ni toi. Qui l’égare en crée une nouvelle ; l’ancienne cesse de valoir à cet instant.
Tu la crées sous « Réglages → App et données → API ». Elle voyage dans l’en-tête de la requête, comme Authorization: Bearer tm_key_… ou comme X-Tellmelo-Key. Pas dans la barre d’adresse, car ce qui s’y trouve finit dans les journaux d’accès, dans l’historique du navigateur et dans le referer de chaque lien.
Pas dans la barre d’adresse. Ce qui s’y trouve finit dans le journal d’accès de chaque serveur intermédiaire, dans l’historique du navigateur et dans le referer de chaque lien. Une clé n’y a pas sa place.
La même clé charge aussi les images. Chaque url d’une réponse pointe vers /api/media de cette instance ; envoie-y aussi la clé dans l’en-tête, et l’image revient, pour autant que ton compte ait le droit de la voir.
Une clé porte deux droits, et chaque chemin des tableaux ci-dessous dit lequel il lui faut. Deux et pas cinq : un droit qu’on ne sait pas s’expliquer en une phrase est un droit qu’on coche sans lire. Et la ligne honnête passe entre regarder et changer.
read : regarder. Les publications publiques, les profils, les communautés et les tags, et ton propre compte tel que tu le vois : fil, notifications, conversations, messages.
write : changer. Tout ce qui se passe en ton nom : publier, répondre, voter, envoyer des messages, suivre, rejoindre, bloquer, marquer des notifications comme lues.
Ce qu’aucune clé ne peut
Aucune clé n’atteint les données de ton compte : ni mot de passe, ni adresse e-mail, ni type de compte, ni lieu, ni rôle, ni suppression. Ni les connexions, ni les appareils de notification, ni les clés elles-mêmes : une clé capable d’émettre des clés ne pourrait plus être coupée. Ni l’administration, ni la direction d’une communauté, car dissoudre une communauté ou la transmettre est une décision sur les publications d’autrui. Ce que le mot de passe garde, aucune clé ne le peut : un secret posé dans un script sur la machine d’un autre ne doit pas pouvoir ce que peut la connexion. Prendre un compte coûte toujours la connexion.
Requêtes et réponses
Du JSON partout. Chaque réponse est en application/json, en UTF-8, erreurs comprises. Seules les images arrivent en images.
Ce que tu envoies. Un POST porte ses champs sous forme d’objet JSON dans le corps. Les paramètres de l’adresse complètent ce que le corps ne nomme pas ; si les deux nomment le même champ, le corps l’emporte.
Les dates sont des nombres entiers de millisecondes depuis le 1er janvier 1970, UTC, comme la base de données les garde. Aucun fuseau horaire à mal lire.
Les identifiants sont des chaînes. Ne les découpe pas et ne te fie pas à leur forme ; compare-les uniquement en entier.
Chaque champ est toujours là. Ce qui n’existe pas vaut null, jamais absent ; un nombre est toujours un nombre, une liste toujours une liste, vide s’il le faut.
Les textes sont du texte brut, tels qu’écrits. Les #tags, les @noms et les liens restent tels quels, de même que les émojis propres à l’instance, sous la forme :name: ; leurs images sont listées sous /emojis.
Les images sont des adresses relatives à cette instance, /api/media?id=…. Charge-les avec la même clé dans l’en-tête ; sans elle, la réponse est 401.
Pages
Chaque liste prend limit et cursor et répond par items et next. Tu continues en renvoyant le next de la dernière réponse comme cursor ; quand next est vide, la fin est atteinte. Une page pleine peut tout de même être la dernière, et qui ne s’arrête qu’à une page vide demande une fois de trop. Le curseur est opaque : une place dans une liste, pas un instant. Ne le démonte pas et n’en fabrique pas toi-même ; ce qu’il contient peut changer sans qu’aucun chemin ne change.
Une page contient 20 entrées sans limit, 50 au plus. Quelques listes ne se feuillettent pas du tout : c’est indiqué à leur chemin, et leur next vaut toujours null.
Seulement ce qui est nouveau
Chaque réponse porte un ETag. Un programme qui redemande sans cesse devrait renvoyer le dernier comme If-None-Match : si rien n’a changé depuis, la réponse est 304 et ne porte pas de corps. C’est la différence entre une liste qui passe sur le fil chaque minute et une qui passe quand il y a quelque chose dedans, pour ta machine autant que pour celle-ci.
Deux exceptions, toutes deux voulues : /feed ne porte pas d’ETag, parce que son ordre bouge avec le temps et que chaque réponse est différente ; et une écriture ne répond jamais 304. Deux publications identiques sont deux publications.
Limites
Une clé peut faire 120 requêtes par minute, 600 avec l’abonnement « Organisation », à moins que l’administration ne lui ait fixé un autre nombre. La limite vaut par clé, pas par compte et pas par adresse. Au-delà, la réponse est 429 et rien ne s’est passé : la requête a été refusée, pas exécutée. Attends une minute et renvoie-la ; un programme qui bute régulièrement devrait ralentir plutôt que redemander aussitôt.
En plus de la limite de la clé, les écritures comptent dans les mêmes limites que dans l’application : combien de publications, de réponses ou de relations en quelques minutes. Elles aussi répondent 429 avec le code rate_limited.
En-têtes
Les noms sont ceux que toute bibliothèque cliente connaît déjà. Aucun n’est obligatoire, sauf la clé.
Ce que tu envoies
En-tête
Signification
Authorization
Porte la clé : Bearer tm_key_…. La voie habituelle.
X-Tellmelo-Key
La clé, en alternative à Authorization, pour les outils qui utilisent cet en-tête pour autre chose.
Content-Type
application/json, pour une requête avec un corps.
If-None-Match
L’ETag de la dernière réponse. Si rien n’a changé depuis, la réponse est 304, sans corps.
Ce qui revient
En-tête
Signification
ETag
L’empreinte de cette réponse, marquée comme faible (W/). Renvoie-la comme If-None-Match.
X-RateLimit-Limit
Combien de requêtes cette clé peut faire par minute.
X-RateLimit-Remaining
Combien il en reste dans la minute en cours.
X-RateLimit-Reset
Quand la minute suivante commence, en secondes depuis 1970, UTC.
X-Tellmelo-Scope
Ce que cette clé peut faire : read ou read write.
Retry-After
Avec un 429 : combien de secondes attendre avant de redemander.
WWW-Authenticate
Avec un 401 pour une clé absente : Bearer, la façon dont une clé est attendue.
Cache-Control
no-store : aucun proxy intermédiaire ne peut garder une réponse, car elle dépend de la clé qui demande. Ton propre programme peut quand même la vérifier avec l’ETag.
Quand quelque chose ne marche pas
Les erreurs arrivent en JSON avec deux champs : un code anglais fixe dans error, que ton programme peut comparer, et une phrase dans message pour la personne devant, avec le code d’état qui va avec. Le code ne change pas ; la phrase peut changer, et elle peut changer dans chaque langue : un programme qui compare la phrase casse un jour que personne n’a annoncé.
{ "error": "rate_limited",
"message": "Too many requests. Try again in a minute.",
"limit": 120 }
Certaines erreurs apportent un champ de plus : docs avec un 401 pour une clé absente, limit avec un 429.
Statut
Code
Signification
400
bad_request
La requête est illisible, un champ obligatoire manque, ou une valeur ne fait pas partie de celles permises. Le message dit laquelle.
401
key_missing
Pas de clé dans l’en-tête.
401
key_invalid
La clé n’est pas valable : mal recopiée, remplacée par une nouvelle, ou son compte est suspendu. Lequel des trois, ce n’est volontairement pas dit.
401
unauthorized
Refusé comme non connecté, pour une autre raison que la clé. Rare, et une raison de regarder le compte derrière la clé.
403
scope_missing
Il manque à la clé le droit dont ce chemin a besoin : le plus souvent write pour une clé qui peut seulement lire.
403
account_data_locked
Cela touche aux données de ton compte, qu’aucune clé n’atteint : mot de passe, adresse e-mail, suppression et ce genre de choses.
403
forbidden
Ton compte n’a pas le droit de faire cela : le même refus que dans l’application, par exemple un droit retiré ou un blocage.
404
unknown_path
Ce chemin n’existe pas, ou pas avec cette méthode.
404
not_found
Le chemin existe, mais pas ce qu’il désigne, ou tu n’as pas le droit de le voir. Les deux ne sont pas distingués.
409
conflict
Cela entre en conflit avec ce qui existe déjà, par exemple un nom déjà pris.
413
too_large
Trop grand : un texte ou une requête au-delà de ce que cette instance accepte.
422
unprocessable
Lisible, mais pas possible sous cette forme.
429
rate_limited
Trop de requêtes. Rien n’a été fait ; attends et renvoie-la.
500
internal_error
Quelque chose a échoué de notre côté, pas du tien. C’est consigné en entier sur le serveur.
Versions
La version est dans le chemin. Tant qu’il y est écrit v2, ces chemins et leurs champs restent tels quels ; ce qui s’ajoute vient à côté.
Les ajouts font monter le second chiffre : 2.1 a apporté /emojis et le marquage d’une conversation comme lue. 2.4 a retiré le champ contentWarning, car les avertissements de contenu n’existent plus. 2.5 a retiré le champ alt des images, car les descriptions d’images n’existent plus. 2.6 ajoute le type de notification team pour le nouveau travail de l’équipe. Chaque chemin indique depuis quelle version il existe, et la racine dit quelle version tourne.
Points d’accès
Tous les chemins d’un coup d’œil, puis chacun en détail : ce qu’il prend, un exemple de requête et ce qui revient.
Lire les publications publiques, publier les tiennes et les retirer.
GET/api/v2/posts
Les publications publiques, les plus récentes d’abord.
Droit read
paginé
avec ETag
depuis v2.0
Sur les chemins publics, les réactions ne sont pas comptées : counts.likes et counts.reposts valent 0 et pinned vaut false (une coupe, pas une mesure).
Les publications d’une communauté ne s’atteignent pas ici, ni dans la liste ni par leur id. Elles se lisent sous /communities/{id}/posts.
Paramètres
Nom
Type
Signification
limitdans l’adresse
integerfacultatif
Combien d’entrées tient une page : 20 par défaut, 50 au plus.
cursordans l’adresse
stringfacultatif
Où cela reprend : le next de la réponse précédente. Sans lui, depuis le haut.
Sur les chemins publics, les réactions ne sont pas comptées : counts.likes et counts.reposts valent 0 et pinned vaut false (une coupe, pas une mesure).
Les publications d’une communauté ne s’atteignent pas ici, ni dans la liste ni par leur id. Elles se lisent sous /communities/{id}/posts.
Une publication a besoin d’un texte ou d’un sondage. Sa longueur, le nombre de réponses d’un sondage et combien de publications en combien de temps sont fixés par cette instance ; au-delà, la réponse est 400 ou 429, avec un message qui dit lequel.
On ne peut pas encore joindre d’images via l’API, seulement dans l’application.
Paramètres
Nom
Type
Signification
textdans le corps
stringfacultatif
Le texte lui-même : de la publication, de la réponse ou du message.
communitydans le corps
stringfacultatif
L’id de la communauté où va la publication. Sans elle, en dehors de toute communauté.
quotesdans le corps
stringfacultatif
L’id de la publication que celle-ci cite.
polldans le corps
string[]facultatif
Les options de réponse d’un sondage, comme une liste de textes. Combien sont permises, l’instance le fixe.
Exemple de requête
curl -X POST \
-H "Authorization: Bearer tm_key_…" \
-H "Content-Type: application/json" \
-d '{"text":"The bees are back in the garden 🐝 #garden"}' \
"https://tellmelo.com/api/v2/posts"
La conversation sous une publication : lue comme une liste que parentId transforme en arbre, écrite en répondant à la publication ou à une réponse.
GET/api/v2/posts/{id}/replies
Les réponses à une publication, telles que tu les vois : ce qu’a écrit un compte bloqué reste dehors.
Droit read
paginé
avec ETag
depuis v2.0
La liste est plate et dans l’ordre d’écriture ; parentId en fait un arbre. Une page contient des fils entiers, une réponse n’arrive donc jamais sans celle à laquelle elle répond. Ce qu’a écrit un compte que tu as bloqué, ou qui t’a bloqué, est laissé de côté. Deux clés peuvent voir des listes différentes.
Paramètres
Nom
Type
Signification
iddans le chemin
stringobligatoire
L’id d’une publication.
limitdans l’adresse
integerfacultatif
Combien d’entrées tient une page : 20 par défaut, 50 au plus.
cursordans l’adresse
stringfacultatif
Où cela reprend : le next de la réponse précédente. Sans lui, depuis le haut.
Sous une publication en mode lent, chaque personne peut répondre une fois toutes les 10 minutes ; une réponse de plus reçoit 429 avec le délai dans le message. Le mode ne s’applique ni à l’auteur ni aux comptes qu’il suit.
Paramètres
Nom
Type
Signification
iddans le chemin
stringobligatoire
L’id d’une publication.
textdans le corps
stringobligatoire
Le texte lui-même : de la publication, de la réponse ou du message.
parentIddans le corps
stringfacultatif
L’id de la réponse à laquelle celle-ci répond. Sans elle, directement à la publication.
Exemple de requête
curl -X POST \
-H "Authorization: Bearer tm_key_…" \
-H "Content-Type: application/json" \
-d '{"text":"Same here, the lavender is full of them."}' \
"https://tellmelo.com/api/v2/posts/5f0c2a9e-8d41-4b7a-9c3e-2e61d0f4a7b1/replies"
Les publications publiques d’un profil, les plus récentes d’abord.
Droit read
paginé
avec ETag
depuis v2.0
Sur les chemins publics, les réactions ne sont pas comptées : counts.likes et counts.reposts valent 0 et pinned vaut false (une coupe, pas une mesure).
Les publications d’une communauté ne s’atteignent pas ici, ni dans la liste ni par leur id. Elles se lisent sous /communities/{id}/posts.
Paramètres
Nom
Type
Signification
handledans le chemin
stringobligatoire
L’identifiant court d’un profil.
limitdans l’adresse
integerfacultatif
Combien d’entrées tient une page : 20 par défaut, 50 au plus.
cursordans l’adresse
stringfacultatif
Où cela reprend : le next de la réponse précédente. Sans lui, depuis le haut.
Les publications publiques d’une communauté, les plus récentes d’abord.
Droit read
paginé
avec ETag
depuis v2.0
Sur les chemins publics, les réactions ne sont pas comptées : counts.likes et counts.reposts valent 0 et pinned vaut false (une coupe, pas une mesure).
Paramètres
Nom
Type
Signification
iddans le chemin
stringobligatoire
L’id d’une communauté.
limitdans l’adresse
integerfacultatif
Combien d’entrées tient une page : 20 par défaut, 50 au plus.
cursordans l’adresse
stringfacultatif
Où cela reprend : le next de la réponse précédente. Sans lui, depuis le haut.
Une recherche sur les publications, les noms, les identifiants courts et les tags.
Droit read
avec ETag
depuis v2.0
Ne cherche que dans ce qui est public : publications hors communautés, profils et tags. limit compte par type : 20 peut ramener jusqu’à 20 publications, 20 profils et 20 tags.
Paramètres
Nom
Type
Signification
qdans l’adresse
stringobligatoire
Les mots cherchés.
typedans l’adresse
stringfacultatif
Quel genre de résultat. Sans lui, tous les genres.allpostsprofilestags
limitdans l’adresse
integerfacultatif
Combien d’entrées tient une page : 20 par défaut, 50 au plus.
Les émojis propres à l’instance, avec l’adresse de leurs images.
Droit read
avec ETag
depuis v2.1
Dans les textes, un émoji de cette instance apparaît sous la forme :name:. Remplace-le par l’image de cette liste ; un nom qui n’y figure pas reste du texte : il a été supprimé ou n’a jamais existé.
Pas d’ETag ici : l’ordre bouge avec le temps, chaque réponse est donc différente. Une liste commencée reste pourtant la même jusqu’au bout : next porte le moment où elle a commencé.
Paramètres
Nom
Type
Signification
tabdans l’adresse
stringfacultatif
Quel fil : for-you, following, latest ou bookmarks. latest par défaut.for-youfollowinglatestbookmarks
tagdans l’adresse
stringfacultatif
Seulement les publications portant ce tag. Sans lui, aucun filtre.
limitdans l’adresse
integerfacultatif
Combien d’entrées tient une page : 20 par défaut, 50 au plus.
cursordans l’adresse
stringfacultatif
Où cela reprend : le next de la réponse précédente. Sans lui, depuis le haut.
Ce qui s’est passé autour de ton compte, lisible page par page, pour qu’un programme puisse rattraper ce qu’il a manqué.
GET/api/v2/notifications
Tes propres notifications, les plus récentes d’abord, feuilletables, pour qu’un programme rattrape ce qu’il a manqué.
Droit read
paginé
avec ETag
depuis v2.0
Lire ne marque rien comme lu ; c’est POST /notifications/read qui le fait. Plusieurs évènements du même type sur la même publication sont regroupés en une ligne, et more dit combien.
Paramètres
Nom
Type
Signification
limitdans l’adresse
integerfacultatif
Combien d’entrées tient une page : 20 par défaut, 50 au plus.
cursordans l’adresse
stringfacultatif
Où cela reprend : le next de la réponse précédente. Sans lui, depuis le haut.
Les messages d’une conversation, les plus récents d’abord.
Droit read
paginé
avec ETag
depuis v2.0
Lire ne marque rien comme lu : un programme qui récupère en arrière-plan n’a rien montré à personne. C’est POST /conversations/{with}/read qui le fait.
Paramètres
Nom
Type
Signification
withdans le chemin
stringobligatoire
L’id du compte avec qui tu parles. Une conversation n’a pas d’id à elle : c’est l’autre compte, la même valeur que la boîte appelle with.
limitdans l’adresse
integerfacultatif
Combien d’entrées tient une page : 20 par défaut, 50 au plus.
cursordans l’adresse
stringfacultatif
Où cela reprend : le next de la réponse précédente. Sans lui, depuis le haut.
Les mêmes règles que dans l’application s’appliquent : on ne peut pas écrire à qui t’a bloqué, et les réglages de l’autre personne comptent. La réponse dit alors pourquoi.
On ne peut pas encore joindre d’images via l’API, seulement dans l’application.
Paramètres
Nom
Type
Signification
withdans le chemin
stringobligatoire
L’id du compte avec qui tu parles. Une conversation n’a pas d’id à elle : c’est l’autre compte, la même valeur que la boîte appelle with.
textdans le corps
stringobligatoire
Le texte lui-même : de la publication, de la réponse ou du message.
replyTodans le corps
stringfacultatif
L’id d’un message précédent de cette conversation auquel celui-ci répond. Depuis 2.2.
Exemple de requête
curl -X POST \
-H "Authorization: Bearer tm_key_…" \
-H "Content-Type: application/json" \
-d '{"text":"See you on Saturday at the market!"}' \
"https://tellmelo.com/api/v2/conversations/a3e1f7c2-54b9-4d0e-8f16-7b2c9d4e1a05/messages"
Aimer, enregistrer, republier, suivre, rejoindre et bloquer : un seul chemin pour tout, établi et retiré avec active.
POST/api/v2/relations
Aimer, garder, partager, suivre, rejoindre, bloquer, masquer, selon kind.
Droit write
depuis v2.0
target est une publication pour like, save et repost, une communauté pour join, un compte pour follow, block et mute, toujours par son id. active: false retire la relation. Personne ne peut suivre par-dessus un blocage, dans aucun sens. Seule la personne qui masque voit le masquage.
Paramètres
Nom
Type
Signification
kinddans le corps
stringobligatoire
Quelle relation : like, save, repost, follow, join, block ou mute (depuis 2.2).likesaverepostfollowjoinblockmute
targetdans le corps
stringobligatoire
Ce que la relation vise, par son id : une publication, un profil ou une communauté, selon kind.
activedans le corps
booleanfacultatif
Si la relation doit tenir : true la pose, false la retire.
Une notification. Une ligne peut regrouper plusieurs évènements du même type.
Champ
Type
Signification
id
string
L’identifiant de la notification.
kind
string
Ce qui s’est passé.
reply — Quelqu’un t’a répondu.
like — Quelqu’un aime ta publication.
repost — Quelqu’un a republié ta publication.
follow — Quelqu’un te suit.
mention — Quelqu’un t’a mentionné.
group_mention — Quelqu’un a mentionné un groupe que tu diriges ; text est son nom.
message — Quelqu’un t’a écrit un message.
scheduled — Une de tes publications programmées est parue.
reminder — Un rappel sur une publication enregistrée est arrivé.
report — Ce qu’est devenu un signalement que tu as envoyé.
moderation — Une décision sur ton compte : un avertissement, une restriction, un recours.
team — Nouveau travail pour l’équipe, uniquement pour propriétaires, admins et modérateurs : signalements, recours, liens soumis, demandes, demandes de vérification et résiliations.
text
stringou null
Seulement pour les signalements et la modération : le texte qui l’accompagne. Sinon null : la phrase d’une notification, c’est ton programme qui la construit.
L’id du message auquel celui-ci répond (null s’il ne répond à aucun). Depuis 2.2.
createdAt
integer
Quand il a été envoyé.
Exemple
{
"id": "7c6b5a49-3827-4165-9f0e-d1c2b3a49586",
"text": "See you on Saturday at the market!",
"from": "a3e1f7c2-54b9-4d0e-8f16-7b2c9d4e1a05",
"to": "d4c3b2a1-6e5f-4a7b-9c8d-1e2f3a4b5c6d",
"read": true,
"media": [],
"replyTo": null,
"createdAt": 1758624060000
}
Created
La réponse d’une écriture qui a créé quelque chose.
Champ
Type
Signification
id
string
L’identifiant de ce qui a été créé.
scheduledFor
integerou null
Quand cela apparaît, si la publication a été programmée (sinon null).
deleteAt
integerou null
Quand cela se supprime tout seul, si c’était réglé (sinon null).
Le même tableau à partir duquel cette page est bâtie est servi sous /api/v2/openapi.json : chemins, paramètres, droits et les formes qui reviennent. Un générateur de clients peut le lire, et il ne peut pas s’écarter de l’API, car la page, le routeur et la description viennent d’une seule liste.
https://tellmelo.com/api/v2/openapi.json
Ce qu’est devenue v1
v1 est supprimée. Les anciens chemins sous /api/v1/ répondent 410 et indiquent dans le corps où aller. Pas de redirection, car v2 répond sous une autre forme, et un programme qui la suivrait recevrait un 200 qu’il ne sait pas lire. Il n’y avait alors pas encore de comptes publics, donc personne avec un programme dessus ; la retirer plus tard aurait voulu dire ne jamais la retirer.
Ce que nous attendons
Les mêmes principes que partout ailleurs : pas de harcèlement, pas de spam, pas de contenus d’autrui sans en avoir le droit. Un programme n’excuse rien : tu réponds de ce que ta clé écrit.