pages(),
blogPosts(), testimonials() …), and every answer is a typed model. How the calls themselves work
(arguments, models, ids, scopes, paging) is the same as in plain TypeScript:
TypeScript → Calling the API. This page shows where they go in AdonisJS.
Read in a controller
The controller
Terminal
app/controllers/blog_posts_controller.ts
findBlog() (and every find…()) answers null for a 404 instead of throwing.The routes
start/routes.ts
#generated/controllers is regenerated by node ace serve and node ace test; run
node ace codegen before a bare tsc.Write, after your own validation
Validate what your visitors send with VineJS first, so a bad request never reaches the site. This one saves a visitor’s testimonial as a draft for an editor to review and publish in the CMS:start/routes.ts
A draft write needs the type’s write scope, here
content:testimonials:write. Without
aposMode: 'draft' the create also takes it live, which needs content:testimonials:publish too
(What an API key reaches).Upload a visitor’s file
The site reads a file’s type from its name, so keep the extension:app/controllers/attachments_controller.ts
start/routes.ts
content:images:write here). A key with a signing secret
signs it by its SHA-256, as every write (Signing requests).
Map SDK errors to responses
Anything the SDK throws is anAttractError, and each carries the site’s own HTTP status. Left alone,
AdonisJS’s exception handler answers your caller with that status, so a key the site refuses (401)
would look like your caller isn’t signed in. Map them once:
app/exceptions/handler.ts
Reported, never leaked
report() logs each one with its message (the site, route and status), never a key. Your caller
sees only your own words.Retries already done
The SDK retried what was safe before it threw: a
RateLimited here has already waited.
What is retried.Long lists and slow calls
One page per request
A controller reads one page (
listBlogs({ page })); …All() walks every page, best in a job; …Pick() walks it for only the fields you name (Find an id).AI routes set their own timeout
Run them from a queue job, not a request: see Jobs, cache and health.
Next: testing
Japa tests with
fakeAttract().