pbflow.de shitpost API

A small public API that returns one assembled anime shitpost as a finished PNG. Selection is random by default. One filter exists: tag, which narrows the images to one or more anime series. Nothing else is filtered and there is no personalisation.

PNG in one request

This URL responds with image/png and nothing else:

https://pbflow.de/api?k=mnbxkAvCrP_1XLRNu8FxWu6G

The response body is the PNG itself.

JSON, if the metadata is useful

https://pbflow.de/api?k=mnbxkAvCrP_1XLRNu8FxWu6G&format=json
{"ok":true,
 "id":"...",
 "image_url":"https://pbflow.de/output/<id>.png",
 "page_url":"https://pbflow.de/output/<id>",
 "template_id":137,
 "image_ids":[412,1987],
 "matched_on":[],
 "ignored":[],
 "catalog_version":1,
 "expires_at":"..."}

image_url points at the same rendered PNG and can be fetched or linked. Images are removed 24 hours after they are created, so a stored URL stops resolving after that.

Tags

tag takes a comma-separated list of series. The images are then drawn only from those series:

https://pbflow.de/api?k=mnbxkAvCrP_1XLRNu8FxWu6G&tag=nagatoro,one-piece&format=json

Two fields in the response say what happened:

{"...":"...",
 "template_id":58,
 "image_ids":[1204],
 "matched_on":["nagatoro"],
 "ignored":["one-piece"],
 "catalog_version":1}

In the example above, one-piece is not in the catalogue, so it was dropped. That is what a guessed value looks like.

Where the values come from

/api/facets is the only valid source for tag values. It needs no token:

https://pbflow.de/api/facets
{"ok":true,
 "catalog_version":1,
 "series":[{"id":"nagatoro","label":"Don’t Toy With Me, Miss Nagatoro","image_count":41},
           {"id":"k-on","label":"K-On!","image_count":12}]}

Do not guess values. Read the list, then send the id strings from it. A value that is not on the list cannot match anything — there is no fuzzy matching, no partial matching and no correction of typos. The response is cacheable for five minutes; fetch it once per session, not once per request — it counts against the same rate limit as /api.

image_count is the number of images behind that series. It is worth reading: a series with a single image can only be combined with the single-image layouts, so posts for it will look less varied.

A few common alternative spellings resolve as well, but only the id values are part of the contract. Use those.

Rules

What tags are not

Tags are thematic: they name a series or franchise. They are not a style, a mood or a kind of humour. tag=deadpan does not exist and is ignored — there is no humour axis in this data, and no filter can invent one.

character is still accepted and still has no effect. It does not narrow anything.

No match is not an error

If nothing resolves, the API does not fail. It returns 200 with an ordinary post, matched_on: [], the dropped values in ignored, and a note saying the selection was random. Treat that as "your tags did not apply", not as a failed request.

The same holds if catalog_version comes back as null and /api/facets returns an empty series list: the catalogue is not loaded, every value lands in ignored, and results are random until it is back.

Access

Responses other than 200