Questa è una traduzione. Fa fede la versione tedesca: dove questo testo se ne discosta, vale il tedesco. Puoi cambiare lingua in fondo alla pagina.
Indice
Panoramica
v2 è l’API di tellmelo per i programmi tuoi. Ogni richiesta porta una chiave, ogni risposta è JSON e ogni elenco si sfoglia allo stesso modo. Ciò che accade dietro una chiave passa per le stesse regole di un clic nell’applicazione: limiti di ritmo, sospensioni, diritti ritirati e le impostazioni di questa istanza valgono qui allo stesso modo.
Ogni percorso inizia con /api/v2 all’indirizzo di questa istanza, quello usato negli esempi di questa pagina.
Richieste e risposte sono JSON in UTF-8. Nomi dei campi, codici e valori sono in inglese e restano in inglese.
Una chiave agisce come il tuo account e mai oltre: ciò che non puoi vedere nell’applicazione, nessuna chiave può leggerlo.
https://tellmelo.com/api/v2
Avvio rapido
Crea una chiave in «Impostazioni → App e dati → API» e copiala. Viene mostrata una sola volta.
Interroga con essa la radice. La risposta dice quale versione è in funzione, che cosa può fare la chiave e quante richieste le restano in questo minuto.
Da lì in poi ogni percorso funziona allo stesso modo: la chiave nell’intestazione, JSON in risposta e, per le liste, items e next.
Come proseguire: /me per il tuo profilo, /posts per ciò che è pubblico, /feed per ciò che l’applicazione ti mostra.
La tua chiave
C’è esattamente una chiave per account, legata al tuo identificativo utente. Comincia con tm_key_, così uno scanner la riconosce dove non dovrebbe stare. Viene mostrata una volta sola, nel momento in cui nasce; dopo resta qui solo la sua impronta, e nessuno te la può rileggere, né noi né tu. Chi la smarrisce ne crea una nuova; la vecchia da quel momento non vale più.
La crei in «Impostazioni → App e dati → API». Viaggia nell’intestazione della richiesta, come Authorization: Bearer tm_key_… oppure come X-Tellmelo-Key. Non nella barra degli indirizzi, perché ciò che sta lì finisce nei registri di accesso, nella cronologia del browser e nel referer di ogni link.
Non nella barra degli indirizzi. Ciò che sta lì finisce nel registro di ogni server intermedio, nella cronologia del browser e nel referer di ogni link. Una chiave lì non ci sta.
La stessa chiave carica anche le immagini. Ogni url in una risposta punta a /api/media di questa istanza; manda anche lì la chiave nell’intestazione e l’immagine torna, per quanto il tuo account possa vederla.
Una chiave porta due diritti, e ogni percorso nelle tabelle qui sotto dice quale dei due gli serve. Due e non cinque: un diritto che non sai spiegarti in una frase è un diritto che spunti senza leggere. E la linea onesta passa fra guardare e cambiare.
read: guardare. I post pubblici, i profili, le community e i tag, e il tuo account così come lo vedi: feed, notifiche, conversazioni, messaggi.
write: cambiare. Tutto ciò che accade a tuo nome: pubblicare, rispondere, votare, inviare messaggi, seguire, entrare, bloccare, segnare le notifiche come lette.
Che cosa nessuna chiave può
Nessuna chiave arriva ai dati del tuo account: né password, né indirizzo e-mail, né tipo di account, né luogo, né ruolo, né eliminazione. Nemmeno gli accessi, né i dispositivi di notifica, né le chiavi stesse: una che potesse emettere chiavi non si potrebbe più spegnere. Nemmeno l’amministrazione, né la guida di una community, perché sciogliere una community o consegnarla è una decisione sui post altrui. Ciò che custodisce la password, nessuna chiave lo può: un segreto che sta in uno script sulla macchina di un altro non deve poter fare ciò che può l’accesso. Prendersi un account costa ancora l’accesso.
Richieste e risposte
JSON ovunque. Ogni risposta è application/json in UTF-8, errori compresi. Solo le immagini arrivano come immagini.
Ciò che invii. Un POST porta i suoi campi come oggetto JSON nel corpo. I parametri dell’indirizzo completano ciò che il corpo non nomina; se entrambi nominano lo stesso campo, vale il corpo.
Gli orari sono numeri interi di millisecondi dal 1° gennaio 1970, UTC, come li conserva la base di dati. Nessun fuso orario da leggere male.
Gli identificativi sono stringhe. Non smontarli e non contare sulla loro forma; confrontali solo per intero.
Ogni campo c’è sempre. Ciò che non esiste è null, mai assente; un conteggio è sempre un numero, una lista sempre una lista, vuota se serve.
I testi sono testo semplice, così come sono stati scritti. #tag, @nomi e link restano come sono, e così gli emoji propri dell’istanza, come :name:; le loro immagini sono elencate in /emojis.
Le immagini sono indirizzi relativi a questa istanza, /api/media?id=…. Caricale con la stessa chiave nell’intestazione; senza, la risposta è 401.
Pagine
Ogni elenco prende limit e cursor e risponde con items e next. Si va avanti rimandando il next dell’ultima risposta come cursor; quando next è vuoto, si è arrivati alla fine. Una pagina piena può comunque essere l’ultima, e chi si ferma solo davanti a una pagina vuota chiede una volta di troppo. Il cursore è opaco: un posto in un elenco, non un istante. Non smontarlo e non costruirtene uno; ciò che contiene può cambiare senza che cambi alcun percorso.
Una pagina contiene 20 voci senza limit, al massimo 50. Alcune liste non si sfogliano affatto: lo dice il loro percorso, e il loro next è sempre null.
Solo ciò che è nuovo
Ogni risposta porta un ETag. Un programma che chiede di continuo dovrebbe rimandare l’ultimo come If-None-Match: se da allora non è cambiato nulla, la risposta è 304 e non porta corpo. È la differenza fra un elenco che attraversa la linea ogni minuto e uno che la attraversa quando c’è qualcosa dentro, per la tua macchina come per questa.
Due eccezioni, entrambe volute: /feed non porta ETag, perché il suo ordine si muove con il tempo e ogni risposta è diversa; e una scrittura non risponde mai 304. Due post uguali sono due post.
Limiti
Una chiave può fare 120 richieste al minuto, 600 con l’abbonamento «Organizzazione», a meno che l’amministrazione non le abbia fissato un altro numero. Il limite vale per chiave, non per account e non per indirizzo. Oltre, la risposta è 429 e non è successo nulla: la richiesta è stata rifiutata, non eseguita. Aspetta un minuto e rimandala; un programma che ci sbatte spesso dovrebbe rallentare invece di richiedere subito.
Oltre al limite della chiave, le scritture contano negli stessi limiti dell’applicazione: quanti post, risposte o relazioni in pochi minuti. Anche questi rispondono 429 con il codice rate_limited.
Intestazioni
I nomi sono quelli che ogni libreria client conosce già. Nessuna è obbligatoria, tranne la chiave.
Ciò che invii
Intestazione
Significato
Authorization
Porta la chiave: Bearer tm_key_…. La via consueta.
X-Tellmelo-Key
La chiave, in alternativa ad Authorization, per gli strumenti che usano quell’intestazione per altro.
Content-Type
application/json, per una richiesta con corpo.
If-None-Match
L’ETag dell’ultima risposta. Se da allora non è cambiato nulla, la risposta è 304 senza corpo.
Ciò che torna
Intestazione
Significato
ETag
L’impronta di questa risposta, marcata come debole (W/). Rimandala come If-None-Match.
X-RateLimit-Limit
Quante richieste può fare questa chiave al minuto.
X-RateLimit-Remaining
Quante ne restano nel minuto in corso.
X-RateLimit-Reset
Quando comincia il minuto successivo, in secondi dal 1970, UTC.
X-Tellmelo-Scope
Che cosa può fare questa chiave: read o read write.
Retry-After
Con un 429: quanti secondi aspettare prima di chiedere di nuovo.
WWW-Authenticate
Con un 401 per chiave mancante: Bearer, il modo in cui è attesa una chiave.
Cache-Control
no-store: nessun proxy intermedio può conservare una risposta, perché dipende dalla chiave che chiede. Il tuo programma può comunque verificarla con l’ETag.
Quando qualcosa non va
Gli errori arrivano in JSON con due campi: un codice inglese fisso in error, che il tuo programma può confrontare, e una frase in message per la persona davanti, con il codice di stato che le corrisponde. Il codice resta; la frase può cambiare, e può cambiare in ogni lingua: un programma che confronta la frase si rompe in un giorno che nessuno ha annunciato.
{ "error": "rate_limited",
"message": "Too many requests. Try again in a minute.",
"limit": 120 }
Alcuni errori portano un campo in più: docs con un 401 per chiave mancante, limit con un 429.
Stato
Codice
Significato
400
bad_request
La richiesta non si legge, manca un campo obbligatorio o un valore non è tra quelli ammessi. Il message dice quale.
401
key_missing
Nessuna chiave nell’intestazione.
401
key_invalid
La chiave non è valida: copiata male, sostituita da una nuova, oppure il suo account è sospeso. Quale delle tre, di proposito non si dice.
401
unauthorized
Rifiutato come non connesso, per un motivo diverso dalla chiave. Raro, e un motivo per guardare l’account dietro la chiave.
403
scope_missing
Alla chiave manca il diritto che serve a questo percorso: di solito write su una chiave che può solo leggere.
403
account_data_locked
Questo riguarda i dati del tuo account, che nessuna chiave raggiunge: password, indirizzo email, eliminazione e simili.
403
forbidden
Il tuo account non può farlo: lo stesso rifiuto dell’applicazione, per esempio un diritto revocato o un blocco.
404
unknown_path
Questo percorso non esiste, o non con questo metodo.
404
not_found
Il percorso esiste, ma non ciò che nomina, oppure non puoi vederlo. Le due cose non vengono distinte.
409
conflict
Si scontra con qualcosa che c’è già, per esempio un nome già preso.
413
too_large
Troppo grande: un testo o una richiesta oltre ciò che questa istanza accetta.
422
unprocessable
Leggibile, ma non possibile in questa forma.
429
rate_limited
Troppe richieste. Non è stato fatto nulla; aspetta e inviala di nuovo.
500
internal_error
Qualcosa è andato storto dalla nostra parte, non dalla tua. È registrato per intero sul server.
Versioni
La versione sta nel percorso. Finché lì c’è scritto v2, questi percorsi e i loro campi restano così; ciò che si aggiunge viene accanto.
Le aggiunte alzano il secondo numero: 2.1 ha portato /emojis e il segnare come letta una conversazione. 2.4 ha tolto il campo contentWarning, perché gli avvisi sui contenuti non esistono più. 2.5 ha tolto il campo alt dalle immagini, perché le descrizioni delle immagini non esistono più. 2.6 aggiunge il tipo di notifica team per il nuovo lavoro del team. Ogni percorso dice da quale versione esiste, e la radice dice quale versione è in funzione.
Percorsi
Tutti i percorsi a colpo d’occhio, poi ciascuno nel dettaglio: che cosa prende, una richiesta d’esempio e che cosa torna.
Un post ha bisogno di testo o di un sondaggio. La lunghezza, il numero di risposte di un sondaggio e quanti post in quanto tempo li stabilisce questa istanza; oltre, la risposta è 400 o 429, con un message che dice quale.
Le immagini non si possono ancora allegare tramite l’API, solo nell’applicazione.
Parametri
Nome
Tipo
Significato
textnel corpo
stringfacoltativo
Il testo stesso: del post, della risposta o del messaggio.
communitynel corpo
stringfacoltativo
L’id della community in cui va il post. Senza, fuori da ogni community.
quotesnel corpo
stringfacoltativo
L’id del post che questo cita.
pollnel corpo
string[]facoltativo
Le opzioni di risposta di un sondaggio, come elenco di testi. Quante ne sono permesse lo fissa l’istanza.
Richiesta d’esempio
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 conversazione sotto un post: letta come una lista che parentId trasforma in albero, scritta rispondendo al post o a una risposta.
GET/api/v2/posts/{id}/replies
Le risposte a un post, così come le vedi tu: ciò che ha scritto un account bloccato resta fuori.
Diritto read
sfogliabile
con ETag
dalla v2.0
La lista è piatta e nell’ordine di scrittura; parentId ne fa un albero. Una pagina contiene fili interi, quindi una risposta non arriva mai senza quella a cui risponde. Ciò che ha scritto un account che hai bloccato, o che ti ha bloccato, resta fuori. Due chiavi possono vedere liste diverse.
Parametri
Nome
Tipo
Significato
idnel percorso
stringobbligatorio
L’id di un post.
limitnell’indirizzo
integerfacoltativo
Quante voci tiene una pagina: 20 come valore predefinito, 50 al massimo.
cursornell’indirizzo
stringfacoltativo
Da dove si riprende: il next della risposta precedente. Senza, dall’alto.
Sotto un post in modalità lenta ogni persona può rispondere una volta ogni 10 minuti; un’altra risposta riceve 429 con l’attesa nel messaggio. La modalità non vale per l’autore né per gli account che segue.
Parametri
Nome
Tipo
Significato
idnel percorso
stringobbligatorio
L’id di un post.
textnel corpo
stringobbligatorio
Il testo stesso: del post, della risposta o del messaggio.
parentIdnel corpo
stringfacoltativo
L’id della risposta a cui questa risponde. Senza, direttamente al post.
Richiesta d’esempio
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"
Gli emoji propri dell’istanza, con l’indirizzo delle loro immagini.
Diritto read
con ETag
dalla v2.1
Nei testi un emoji di questa istanza compare come :name:. Sostituiscilo con l’immagine di questa lista; un nome che non c’è resta testo: è stato eliminato o non è mai esistito.
Qui niente ETag: l’ordine si muove con il tempo, quindi ogni risposta è diversa. Una lista iniziata resta comunque la stessa fino alla fine: next porta il momento in cui è cominciata.
Parametri
Nome
Tipo
Significato
tabnell’indirizzo
stringfacoltativo
Quale feed: for-you, following, latest o bookmarks. latest come valore predefinito.for-youfollowinglatestbookmarks
tagnell’indirizzo
stringfacoltativo
Solo i post con questo tag. Senza, nessun filtro.
limitnell’indirizzo
integerfacoltativo
Quante voci tiene una pagina: 20 come valore predefinito, 50 al massimo.
cursornell’indirizzo
stringfacoltativo
Da dove si riprende: il next della risposta precedente. Senza, dall’alto.
Ciò che è successo intorno al tuo account, leggibile pagina per pagina, perché un programma possa recuperare ciò che ha perso.
GET/api/v2/notifications
Le tue notifiche, le più recenti per prime, sfogliabili, così un programma recupera ciò che si è perso.
Diritto read
sfogliabile
con ETag
dalla v2.0
Leggere non segna nulla come letto; lo fa POST /notifications/read. Più eventi dello stesso tipo sullo stesso post vengono raccolti in una riga, e more dice quanti.
Parametri
Nome
Tipo
Significato
limitnell’indirizzo
integerfacoltativo
Quante voci tiene una pagina: 20 come valore predefinito, 50 al massimo.
cursornell’indirizzo
stringfacoltativo
Da dove si riprende: il next della risposta precedente. Senza, dall’alto.
Valgono le stesse regole dell’applicazione: a chi ti ha bloccato non si può scrivere, e contano le impostazioni dell’altra persona. La risposta dice allora perché.
Le immagini non si possono ancora allegare tramite l’API, solo nell’applicazione.
Parametri
Nome
Tipo
Significato
withnel percorso
stringobbligatorio
L’id dell’account con cui parli. Una conversazione non ha un id suo: è l’altro account, lo stesso valore che la posta chiama with.
textnel corpo
stringobbligatorio
Il testo stesso: del post, della risposta o del messaggio.
replyTonel corpo
stringfacoltativo
L’id di un messaggio precedente di questa conversazione a cui questo risponde. Dalla 2.2.
Richiesta d’esempio
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"
Mi piace, salvare, ricondividere, seguire, unirsi e bloccare: un solo percorso per tutto, impostato e ritirato con active.
POST/api/v2/relations
Mettere mi piace, salvare, condividere, seguire, entrare, bloccare, silenziare, a seconda di kind.
Diritto write
dalla v2.0
target è un post per like, save e repost, una community per join, un account per follow, block e mute, sempre tramite il suo id. active: false ritira la relazione. Nessuno può seguire attraverso un blocco, in nessuna direzione. Solo chi silenzia vede il silenziamento.
Parametri
Nome
Tipo
Significato
kindnel corpo
stringobbligatorio
Quale relazione: like, save, repost, follow, join, block o mute (dalla 2.2).likesaverepostfollowjoinblockmute
targetnel corpo
stringobbligatorio
A che cosa punta la relazione, tramite il suo id: un post, un profilo o una community, a seconda di kind.
activenel corpo
booleanfacoltativo
Se la relazione deve valere: true la mette, false la toglie.
Una notifica. Una riga può raccogliere più eventi dello stesso tipo.
Campo
Tipo
Significato
id
string
L’identificativo della notifica.
kind
string
Che cosa è successo.
reply — Qualcuno ti ha risposto.
like — A qualcuno piace il tuo post.
repost — Qualcuno ha ricondiviso il tuo post.
follow — Qualcuno ti segue.
mention — Qualcuno ti ha menzionato.
group_mention — Qualcuno ha menzionato un gruppo che guidi; text è il suo nome.
message — Qualcuno ti ha scritto un messaggio.
scheduled — Un tuo post programmato è stato pubblicato.
reminder — È arrivato un promemoria su un post salvato.
report — Che cosa è successo a una segnalazione che hai inviato.
moderation — Una decisione sul tuo account: un avvertimento, una limitazione, un ricorso.
team — Nuovo lavoro per il team, solo per proprietari, admin e moderatori: segnalazioni, ricorsi, link inviati, richieste, richieste di verifica e disdette.
text
stringo null
Solo per segnalazioni e moderazione: il testo che l’accompagna. Altrimenti null: la frase di una notifica la costruisce il tuo programma.
L’id del messaggio a cui questo risponde (null se non risponde a nessuno). Dalla 2.2.
createdAt
integer
Quando è stato inviato.
Esempio
{
"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 risposta di una scrittura che ha creato qualcosa.
Campo
Tipo
Significato
id
string
L’identificativo di ciò che è stato creato.
scheduledFor
integero null
Quando compare, se la pubblicazione è stata programmata (altrimenti null).
deleteAt
integero null
Quando si elimina da solo, se è stato impostato (altrimenti null).
La risposta di una scrittura che non ha niente da restituire.
Campo
Tipo
Significato
ok
boolean
Sempre true.
Esempio
{
"ok": true
}
La descrizione leggibile da una macchina
La stessa tabella con cui è costruita questa pagina sta sotto /api/v2/openapi.json: percorsi, parametri, diritti e le forme che tornano. Un generatore di client può leggerla, e non può allontanarsi dall’API, perché la pagina, il router e la descrizione vengono da un solo elenco.
https://tellmelo.com/api/v2/openapi.json
Che fine ha fatto v1
v1 è stata rimossa. I vecchi percorsi sotto /api/v1/ rispondono 410 e dicono nel corpo dove andare. Nessun reindirizzamento, perché v2 risponde in un’altra forma, e un programma che lo seguisse riceverebbe un 200 che non sa leggere. A quel punto non c’erano ancora account pubblici e quindi nessuno con un programma sopra; toglierla più tardi avrebbe voluto dire non toglierla mai.
Che cosa ci aspettiamo
Gli stessi principi di sempre: niente molestie, niente spam, nessun contenuto altrui senza averne diritto. Un programma non scusa nulla: di ciò che scrive la tua chiave rispondi tu.