Start here
What this api is, what it is not, and a call that works in about two minutes.
https://api.acyka.cc/api/v1 answers 43 operations over the
anime catalogue, public profiles, and the lists, shelves and writing of whoever authorised your
application. Every one of them is the same function acyka's own site calls — the cast ordering,
the search that folds ё onto е, the filter that keeps a sequel out of
“similar”. There is no second implementation to disagree with the first.
The shape of it #
- Everything needs a bearer token. No route here reads a cookie, which is why none of them needs a CSRF rule and why a page in a browser can call them cross-site.
- snake_case.
shikimori_id,title_orig,email_verified— the same words in the reference, in acurlanswer, and in five of the six libraries. - A collection answers
{ "items": [...] }, withtotalbeside it wherever the caller pages by offset. A single resource answers as itself, at the top level. - Absent is not zero. A missing follower count means “not yours to know”; a
0means “nobody”. Nothing here collapses the two, and neither should your code.
What is deliberately not here #
Video. The site's player is fed addresses at Kodik, AnimeLib and AniLibria — somebody else's files under somebody else's terms. Serving them to acyka's own player is one argument; handing them to your application as a documented, versioned promise is a different one that nobody has made.
Rooms. A room is one process's memory with a stream hanging off it. The contract you would be holding is “this stays open”, and a deploy is a restart.
Register an application #
At acyka.cc/settings/applications. Keep it confidential if it runs on a server you control, and allow it catalog:read. You get a client id and a secret; the secret is shown once, because
what is stored is an argon2 hash and nothing can produce it again.
Install a library #
bun add @acyka/api # or npm / pnpm / yarn
pip install acyka
cargo add acyka Six of them — TypeScript, Python, Rust, Kotlin, C# and C++ — and they are the same library six times rather than six libraries: the types and the methods are generated from one contract, so none of them can be behind the others. The libraries says what is hand-written in each and why.
The first call #
import { Acyka } from '@acyka/api';
// An application acting for itself. No person signs in, so there is no
// consent screen and nothing to store — the token is minted when it is
// first needed and again when it expires.
const acyka = Acyka.app({
clientId: process.env.ACYKA_ID!,
clientSecret: process.env.ACYKA_SECRET!
});
const found = await acyka.catalogue.listTitles({ q: 'frieren', limit: 5 });
for (const title of found.items) {
console.log(title.id, title.title, title.year, title.score);
} Only catalog:read and people:read can be held this way. Everything
else on this api is about a person, and an application speaking for itself has nobody to act for
— see Authorising for the flow that does.
# the same call, which is the one you can check by hand
# the provider is on acyka.cc — its endpoints hang off the issuer, and
# the discovery document is the authority on all of them
TOKEN=$(curl -s https://acyka.cc/api/oauth2/token \
-u "$ACYKA_ID:$ACYKA_SECRET" \
-d grant_type=client_credentials \
-d scope=catalog:read | jq -r .access_token)
curl "https://api.acyka.cc/api/v1/titles?q=frieren&limit=5" \
-H "Authorization: Bearer $TOKEN" Then #
- The reference — every operation, in seven languages.
- The playground — the same calls, signed in as you, in a browser.
- Rate limits — what you get, and how to be told what is left.