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.
API Maker
The framework for AI era
Your code
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.
Step through it, slow it down, or open the full canvas.
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.
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.
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.
The order is saved with created_by, stamped by the table hook: no client can forget it or fake it.
API level first, instance last. They read the result and can replace it with g.res.output: the internal cost never leaves the server.
A pre hook that throws ends the call with your message. The API does not run, nothing is saved.
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.
A hook on an instance runs for every table in it. A hook on a table runs for all its generated and schema APIs.
Give a hook group names and it runs only for API users in one of those groups, for example audit logs for partners.
Hooks query other tables, read secrets, call external APIs, emit events and import your utility classes.
Every hook has its own active flag. Turn one off to test without it: no restart, no deployment.
g.req.isApiRequestFromUser tells a real client call from an internal one, so a hook can skip calls made by your own code.
Hooks run in the sandbox like custom APIs, or on the native process when you allow it for a trusted hook.
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.
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;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;Every generated and schema API, at the instance, database, table or API level, and every system API. Custom APIs get hooks per version.
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.
Throw in the pre hook. The call stops and the client gets your message in errors.
Documentation