API Maker

The framework for AI era

Your code

Pre & Post Hooks

Run your own code before and after any API, without touching the API itself.

A pre hook runs before an API: it can check the request, change the body, or answer on its own. A post hook runs after it and can change the output. Hooks are TypeScript, work on generated, custom and system APIs, and apply on the next request after you save them.

See it live

Step through it, slow it down, or open the full canvas.

api-maker/features/hooksLive
  • Request
  • Pre hook
  • Post hook
  • Stopped
Levels
4instance to API
Hooks run
0in this tour
Skipped
0not in the group
Saved
0orders

Hooks on four levels. Put a hook on an instance and it runs for every table in it. On a table, for all its APIs. Or on one API. Generated, schema, custom and system APIs all have hooks.

How it works

  1. Hooks on four levels.

    Put a hook on an instance and it runs for every table in it. On a table, for all its APIs. Or on one API. Generated, schema, custom and system APIs all have hooks.

  2. Pre hooks run from the outside in.

    Instance, database, table, then the API. They read and change g.req.body. A hook with group names runs only for API users in those groups.

  3. The API runs with the request as the hooks left it.

    The order is saved with created_by, stamped by the table hook: no client can forget it or fake it.

  4. Post hooks run from the inside out.

    API level first, instance last. They read the result and can replace it with g.res.output: the internal cost never leaves the server.

  5. Throw to stop a call.

    A pre hook that throws ends the call with your message. The API does not run, nothing is saved.

  6. Return a value to answer the call.

    When a hook returns something, that is the response: the API and the post hooks do not run. A plain return only leaves the hook.

What you get

Set once, apply everywhere

A hook on an instance runs for every table in it. A hook on a table runs for all its generated and schema APIs.

Only for some groups

Give a hook group names and it runs only for API users in one of those groups, for example audit logs for partners.

Full access to g

Hooks query other tables, read secrets, call external APIs, emit events and import your utility classes.

Switch on and off

Every hook has its own active flag. Turn one off to test without it: no restart, no deployment.

Know who is calling

g.req.isApiRequestFromUser tells a real client call from an internal one, so a hook can skip calls made by your own code.

Where it runs

Hooks run in the sandbox like custom APIs, or on the native process when you allow it for a trusted hook.

An example

Rules the database cannot hold

Orders must have lines, prices must come from the product table and not from the client, and every change must record who made it. Three pre hooks on the orders table enforce it for the generated APIs, the schema APIs and every app that calls them.

Pre hook on the orders table: stamp the user, refuse empty orderspre-hook.ts
import * as T from 'types';async function main(g: T.IAMGlobal) {    if (!g.req.isApiRequestFromUser) return; // calls from your own code pass through    const order = g.req.body;    if (!order.lines?.length) throw 'An order needs at least one line.';    order.created_by = g.req.auth.authAMDB?.username;}module.exports = main;
Post hook: hide the internal cost from the answerpost-hook.ts
import * as T from 'types';async function main(g: T.IAMGlobal) {    const output = g.res.output;    const rows = Array.isArray(output) ? output : [output];    for (const row of rows) delete row.internal_cost;    g.res.output = output; // the answer the client gets}module.exports = main;

Good to know

  • Stream APIs run pre hooks only: their response is sent while it is read, so post hooks cannot change it.
  • A response served from the cache does not run the hooks.
  • Calls made from your code with g.sys.db skip hooks by default. Pass skipHookRunning: false to run them.

Questions

Which APIs can have hooks?

Every generated and schema API, at the instance, database, table or API level, and every system API. Custom APIs get hooks per version.

In which order do several hooks run?

Pre hooks: instance, database, table, API, and from top to bottom inside a level. Post hooks: the other way round, API first and instance last.

How do I stop a request with an error?

Throw in the pre hook. The call stops and the client gets your message in errors.