Callbacks
Callback reference for fylr plugins — the hooks fylr runs during its own API calls (db pre-save, transitions, webhooks, export, export transport), the unified contract, and how to call back into the A
Callbacks are predefined hooks in fylr's API. When fylr handles a save, a transition or an export, it runs the plugin program you registered for that hook, hands it the relevant data, and reads back the plugin's result. Each hook has its own input and output format — this page is the reference.
Callbacks are registered under callbacks in the manifest, using the same exec map as extensions.
db_pre_save
on POST /api/v1/db, before objects are written
validate or modify objects before they are saved
transition_db_pre_save/<type>
inside a configured transition
the transition's own pre-save hook
webhook_db_pre_save
on a webhook-driven save
pre-save hook for webhook saves
export/<procedure>
after POST /api/v1/export/<id>/start
post-process an export
export_transport
after an export finishes, per transport
deliver the export somewhere
Errors
A callback signals an error by exiting non-zero, or by writing an API-error JSON wrapped under a top-level error key (in which case a zero exit code is fine).
Calling back into the API
Most callbacks run server-side in the file-worker tool chain and frequently need to call back into the fylr API — to read the base config, load or write objects. For this, every callback receives the same set of fields, the unified callback contract, independent of which hook runs:
api_url
always
Base URL to call back into the API. Append /api/v1/… to reach an endpoint.
api_user_access_token
always
OAuth2 access token to call the API as the user the current API call runs as.
api_user
always
The current API user (the who).
plugin_user_access_token
only if configured
Access token of the configured plugin user. Present only if the manifest entry declares a plugin_user. If the plugin user resolves to the current API user, it equals api_user_access_token.
plugin_user
only if configured
The plugin user (the who) for plugin_user_access_token.
A callback therefore always gets a token for the current API user, and additionally a token for the plugin user when one is configured — never one or the other.
These tokens are unbound and short-lived. fylr binds a browser session token to the browser via the fylr-browser-id cookie, so a plugin replaying the user's own token server-side — without that cookie — would be rejected by session binding. fylr therefore hands the plugin freshly issued, session-binding-free tokens that work for the cookieless server-to-server callback and are revoked once the callback returns. Treat them as short-lived; do not persist them.
Where the fields live in the payload
For extensions the payload is the info map, so the fields are at the top level:
api_user_access_token,api_url, …For db_pre_save, transition_db_pre_save and export the payload also carries the hook's own data (the object list, the export object), so the contract fields live under the
infokey:info.api_user_access_token,info.api_url, …
Using them from a callback program:
export — backwards compatibility: the export payload additionally contains a legacy api_callback map ({ "token", "url" }) equivalent to info.api_user_access_token + info.api_url. It is kept so existing export plugins keep working; new export plugins should use the unified contract fields above.
db_pre_save, transition_db_pre_save/<type>, webhook_db_pre_save
db_pre_save, transition_db_pre_save/<type>, webhook_db_pre_saveThis callback runs for each POST /api/v1/db request (or inside a configured transition). It can validate or modify the objects before they are written.
In group mode the payload consists of all individual objects loaded from the database.
Each object includes the currently stored object under the top-level key
_current, if available.Each object carries a
_callback_contextat the top level._callback_context.hashmust be returned in the response to update the object — only returned objects are updated.Returned objects only update the user values, comment, pool, tags and rights. Other fields — especially any ids — are not updated.
The callback receives reverse and bidirectional linked objects at the top level of the object list. The callback must deal with them, or not return them. For bidirectional objects, returning only one side can lead to incomplete objects.
The
_all_fieldsmask is used to render the JSON for the plugin; the plugin must return the data using_all_fields._callback_context.original_maskholds the mask used in the posted object.For inserted objects ids are not yet set, so
_uuid,_global_object_id,_system_object_idand<object>._idare unset;<object>._id_parentmay be0for an as-yet-unknown parent (e.g. in a reverse-hierarchy context).For transitions the
transition.typeis<plugin-name>:<transition-type>.db_pre_saveuses astepslist to run multiple callbacks in order; each step can filter by objecttype.
Example — set a comment on every saved bilder object:
The matching manifest entry is shown in manifest.yml → full example.
export/<procedure>
export/<procedure>Called by POST /api/v1/export/<id>/start after the regular export has run. The export must set produce_options.plugin to <plugin-name>:<procedure>, and <procedure> must be an entry under callbacks.export in the manifest.
The frontend part of the plugin sets:
which runs the manifest entry:
Behaviour:
The payload carries general info (base config in
info.config) and theinfo.exportobject.The plugin writes back the
exportobject and may modify it.export.filesare read back, but only their internal representationexport._files[n].export_file_internal. Sethidden = truethere to keep a file out of the export API.The plugin must set
export._statetodone,done_with_warningsorfailed.failedproduces anEXPORT_FAILEDevent; the others produceEXPORT_FINISH.An
export._plugin_log([]string) is merged into that event.The plugin can create its own file entries; fylr calls back into the plugin per file, passing
export.files[n].export_file_internal.plugin_actionasinfo.plugin_action. Additional plugin files are created on the fly.
Payload (%info.json%)
%info.json%)info.config.system
Base config of the instance.
info.request
Information about the request.
export
The export in API format, enhanced with internal information. Since 6.28.0, present only if the command does not read stdin from body.
export._files[n].export_file_internal
Internal information per file.
plugin_action
Set when the request is for a plugin-exported file.
info.api_user_access_token, info.api_url, info.api_user, info.plugin_user_access_token, info.plugin_user
api_callback
Backwards compatibility only — { "token", "url" }, equivalent to info.api_user_access_token + info.api_url.
Return payload
Return everything from info.export under export (omit the info level). It is written back to the database as is, with only a few checks. info.export._log is read-only and need not be returned.
_state
New export status: done, done_with_warnings, or failed.
_plugin_log
[]string merged into the event fylr writes after the plugin ran.
Per-file, in export._files[n].export_file_internal:
hidden
true hides the file from the external export API (the plugin still sees it).
path
Path appended to /api/v1/export/[n]/file.
content_type
Content-Type shown over the API (the actually-sent type is auto-detected).
plugin_action
Custom action string passed back to the plugin when the file is requested.
export_transport
export_transportRuns after the regular export finishes, once per transport. The transport plugin receives the same payload as an export plugin plus a transport object:
all properties from export
transport
The transport object, with everything needed for the transport.
transport.options
Configuration settings for the transport.
Return payload
The transport reports whether it succeeded and may add information to the event fylr writes; nothing else needs to be returned.
_state
New status: done, done_with_warnings, or failed.
_transport_log
[]string merged into the event fylr writes after the plugin ran.
See also
manifest.yml — register callbacks, the
execmap.Extensions — custom API endpoints (as opposed to hooks).
Anatomy of a Record — the object JSON a
db_pre_savecallback receives and returns.Events and webhooks — the push/pull integration alternatives to synchronous callbacks.
Last updated