Some API feedback #1

Closed
opened 2026-02-26 12:25:51 +00:00 by nikclayton · 1 comment
nikclayton commented 2026-02-26 12:25:51 +00:00 (Migrated from codeberg.org)

(Couldn't see a place for general discussions, so I'm leaving this feedback as an issue. Happy to take this somewhere else if that would be more helpful).

Versioning

Please version the API (version numbers in the API routes, return versioned objects in the response).

Search operators/filters

Please support search operators (e.g., "Search for posts that don't have video attachments").

Please don't do this with special syntax in the query string (i.e., don't copy Mastodon's mistake of special syntax "-has:video" or similar in the query string). Instead, these should be properties in the API.

If you do want to support query syntax too this should be done in the frontend by parsing the query string to generate the API call.

Other Mastodon bugs to avoid:

Search capabilities

Please provide a mechanism that allows a client to determine which search capabilities are available.

For example, right now you might imagine that running a discover server implies that all the capabilities are present. It seems likely that in the future a server operator might want to e.g., provide general search capabilities, but not provide "trends" capabilities. Clients need to be able to discover that.

Similarly, different (versions of) the server might support different search filters, and clients need to be able to discover that as part of determining what UI to show.

api/search offset param

Is this an offset in to the results, or an offset in to the pages?

I.e, if I request /api/search?q=foo&limit=20&offset=1 am I:

  1. Requesting results 2-21 -- offset=1 is relative to the results
  2. Requesting results 21-40 -- offset=1 is relative to the page numbers

?

Offset stability

How do you maintain offset stability across repeated searches?

Suppose I'm searching for a very popular hashtag, with lots of posts coming in. I perform the search (call it Q1), and get the first page of results, at time T.

At time T+5 I repeat the search (Q2), with an offset designed to get the next page of results.

However, at times T+1, T+2, T+3, and T+4 new content comes in that would be at the top of the search results if Q1 was repeated.

Are the results from Q2 going to include posts previously included in Q1? If yes, are clients expected to de-duplicate results? If no, how is de-duplication achieved?

The API examples make it look like you're trying to do a mix of limit/offset based paging and cursor based paging (e.g., as described in https://apidog.com/blog/pagination-in-rest-apis/). You probably want strictly-cursor based paging, since it's unlikely that clients are going to want to jump to a specific page of results.

That also suggests the meta property can be dropped. In a particular, while your dataset is currently small being able to calculate the total number of pages in a result set is easy. As the dataset gets larger that may become more resource intensive.

From a client-author's perspective it's also more important that I can provide a user experience where if the user performs a search, leaves the app for five minutes, and then comes back, I can have the user continue from where they left off, instead of having to wipe and restart the search. I can do that with cursor based pagination, it's not really possible with offset based pagination.

POST support

Please also support POSTing a JSON object that contains the query parameters, as well as GET with a query string.

Language code

Using ISO 639-1 for the language code misses out a lot of languages. Please consider supporting ISO 639-3, https://iso639-3.sil.org/code_tables/639/data.

Incidentally, this also highlights a source of potential confusion in the future, as language is a very generic property name. For things like this please consider using very precise property names (e.g., deprecate language now for a language_iso_639_1 property, making it easier to understand and update to something else in the future).

type

type is either "all types" or "one type". Please consider extending the API to allow "these types" as an option.

Related / alternatively:

  • Why have a type property? Use /api/search for clients that want everything, and the more specific /api/search/... routes for clients that want a specific type.
  • Why is the type value actors, but the equivalent API route /api/search/accounts?

Result ordering

How are search (not trends) results ordered?

Inconsistent response "shapes"

The "shape" of the response from /api/search and /api/search/* is different. In the more specific search queries you remove the intermediate posts, actors, hashtags, ... properties and make the data property a list.

Please don't do that. Keep the same shape of data in the response, and omit the properties (posts, actors, etc) if there are no results of that type.

Empty array, null, or missing property for no results?

It's not specified what a successful response with no results looks like? Is it:

  1. The data property is always present, and will be the empty list, data: []?
  2. The data property is always present, and will be null, data: null?
  3. The data proeprty is not present?

Same question, but where a search has results of one type, but not of another type. Are the posts, actors etc properties present but empty, present but null, or missing?

instances property

What's that for?

As a general comment, I thought the term "instance" was considered deprecated in favour of "server" (e.g., new language on https://joinmastodon.org/servers).

/api/instances query and specifying the information to return

(not specific to this query, but it's a good examplar) Consider allowing clients to specify what information they want returned from the query.

For example, this query could be used to provide autocomplete functionality in a client. For that the client may not need a lot of the data that is returned by default. Allowing the client to, e.g., request just the server names in the response would reduce the amount of data the client needs to receive and process, and the amount of data the server needs to process and send.

More...

I've got more questions about the interpretation of the data from the various responses, but I don't want to send too much your way at once.

Although if you haven't already it might be worth looking at the issues raised in the discussion over at https://github.com/mastodon/fediverse_auxiliary_service_provider_specifications/pull/45, regarding a similar service.

(Couldn't see a place for general discussions, so I'm leaving this feedback as an issue. Happy to take this somewhere else if that would be more helpful). ## Versioning Please version the API (version numbers in the API routes, return versioned objects in the response). ## Search operators/filters Please support search operators (e.g., "Search for posts that don't have video attachments"). Please **don't** do this with special syntax in the query string (i.e., don't copy Mastodon's mistake of special syntax "-has:video" or similar in the query string). Instead, these should be properties in the API. If you **do** want to support query syntax too this should be done in the frontend by parsing the query string to generate the API call. Other Mastodon bugs to avoid: - https://github.com/mastodon/mastodon/issues/31142 - https://github.com/mastodon/mastodon/issues/31078 - https://github.com/mastodon/mastodon/issues/31057 ## Search capabilities Please provide a mechanism that allows a client to determine which search capabilities are available. For example, right now you might imagine that running a discover server implies that all the capabilities are present. It seems likely that in the future a server operator might want to e.g., provide general search capabilities, but not provide "trends" capabilities. Clients need to be able to discover that. Similarly, different (versions of) the server might support different search filters, and clients need to be able to discover that as part of determining what UI to show. ## api/search `offset` param Is this an offset in to the results, or an offset in to the pages? I.e, if I request `/api/search?q=foo&limit=20&offset=1` am I: 1. Requesting results 2-21 -- `offset=1` is relative to the results 2. Requesting results 21-40 -- `offset=1` is relative to the page numbers ? ## Offset stability How do you maintain offset stability across repeated searches? Suppose I'm searching for a very popular hashtag, with lots of posts coming in. I perform the search (call it Q1), and get the first page of results, at time T. At time T+5 I repeat the search (Q2), with an offset designed to get the next page of results. However, at times T+1, T+2, T+3, and T+4 new content comes in that would be at the top of the search results if Q1 was repeated. Are the results from Q2 going to include posts previously included in Q1? If yes, are clients expected to de-duplicate results? If no, how is de-duplication achieved? The API examples make it look like you're trying to do a mix of limit/offset based paging and cursor based paging (e.g., as described in https://apidog.com/blog/pagination-in-rest-apis/). You probably want strictly-cursor based paging, since it's unlikely that clients are going to want to jump to a specific page of results. That also suggests the `meta` property can be dropped. In a particular, while your dataset is currently small being able to calculate the total number of pages in a result set is easy. As the dataset gets larger that may become more resource intensive. From a client-author's perspective it's also more important that I can provide a user experience where if the user performs a search, leaves the app for five minutes, and then comes back, I can have the user continue from where they left off, instead of having to wipe and restart the search. I can do that with cursor based pagination, it's not really possible with offset based pagination. ## POST support Please also support POSTing a JSON object that contains the query parameters, as well as GET with a query string. ## Language code Using ISO 639-1 for the language code misses out a lot of languages. Please consider supporting ISO 639-3, https://iso639-3.sil.org/code_tables/639/data. Incidentally, this also highlights a source of potential confusion in the future, as `language` is a very generic property name. For things like this please consider using very precise property names (e.g., deprecate `language` now for a `language_iso_639_1` property, making it easier to understand and update to something else in the future). ## `type` `type` is either "all types" or "one type". Please consider extending the API to allow "these types" as an option. Related / alternatively: - Why have a `type` property? Use `/api/search` for clients that want everything, and the more specific `/api/search/...` routes for clients that want a specific type. - Why is the `type` value `actors`, but the equivalent API route `/api/search/accounts`? ## Result ordering How are search (not trends) results ordered? ## Inconsistent response "shapes" The "shape" of the response from `/api/search` and `/api/search/*` is different. In the more specific search queries you remove the intermediate `posts`, `actors`, `hashtags`, ... properties and make the `data` property a list. Please don't do that. Keep the same shape of data in the response, and omit the properties (`posts`, `actors`, etc) if there are no results of that type. ## Empty array, null, or missing property for no results? It's not specified what a successful response with no results looks like? Is it: 1. The `data` property is always present, and will be the empty list, `data: []`? 2. The `data` property is always present, and will be null, `data: null`? 3. The `data` proeprty is not present? Same question, but where a search has results of one type, but not of another type. Are the `posts`, `actors` etc properties present but empty, present but null, or missing? ## `instances` property What's that for? As a general comment, I thought the term "instance" was considered deprecated in favour of "server" (e.g., new language on https://joinmastodon.org/servers). ## `/api/instances` query and specifying the information to return (not specific to this query, but it's a good examplar) Consider allowing clients to specify what information they want returned from the query. For example, this query could be used to provide autocomplete functionality in a client. For that the client may not need a lot of the data that is returned by default. Allowing the client to, e.g., request just the server names in the response would reduce the amount of data the client needs to receive and process, and the amount of data the server needs to process and send. ## More... I've got more questions about the interpretation of the data from the various responses, but I don't want to send too much your way at once. Although if you haven't already it might be worth looking at the issues raised in the discussion over at https://github.com/mastodon/fediverse_auxiliary_service_provider_specifications/pull/45, regarding a similar service.
tom79 commented 2026-02-27 15:42:43 +00:00 (Migrated from codeberg.org)

We've just deployed version 1.1.0 which addresses several of your points. A new API documentation is available at https://discover.holos.social/api-docs (powered by RapiDoc with live testing).

Concerning the response shapes that differ between /api/search (returns posts, actors, hashtags objects) and /api/search/* (returns flat array), the specific endpoints only return one type, so we simplified the response structure.

We've just deployed version 1.1.0 which addresses several of your points. A new API documentation is available at https://discover.holos.social/api-docs (powered by RapiDoc with live testing). Concerning the response shapes that differ between /api/search (returns posts, actors, hashtags objects) and /api/search/* (returns flat array), the specific endpoints only return one type, so we simplified the response structure.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
tom79/Holos-Discover#1
No description provided.