# Toolkit Endpoints [back to toolkits](README.md) /// [home](../README.md) Custom API routes defined by toolkits. These live under `/tk/app/{toolkit}/` or `/tk/lib/{toolkit}/` depending on the toolkit type. ## Route format ``` POST /tk/app/beepzone/kiosk/scan GET /tk/lib/opensigma/status ``` The path after the toolkit name is matched against endpoint definitions in the toolkit config. ## Endpoint types ### Internal Runs logic within the server process. Can use `pseudo_querys` to execute database queries based on the request payload. No external service needed. ### HTTP Proxies the request to an external HTTP service. The server wraps the payload in a context object (user info, DB context etc), sends it to the upstream URL and returns the response. Can return JSON (wrapped in the standard envelope) or `passthrough` (raw bytes with the upstream content type, useful for file downloads). ### Executable Runs a shell command on the server. The request context is passed as a JSON string argument. Output is parsed as JSON or wrapped in `{ "output": "..." }` if its not valid JSON. ## Request flow 1. verify the toolkit exists and is enabled (404 if not) 2. match the endpoint path in config (404 if not found) 3. check endpoint level permissions for your power level (403 if denied) 4. validate payload against `client_filter` rules (400 if invalid) 5. fetch `inject_db_context` values from the database 6. resolve your toolkit group 7. build the request context 8. apply `overwrite_wrapping` transformations 9. execute based on endpoint type ## Request context The context object sent to backends looks like this: ```json { "user_id": 1, "username": "admin", "power": 100, "core_group_id": 1, "core_group_name": "administrators", "toolkit_group": "managers", "request_id": "abc123", "payload": { ... }, "db_context": { "key": "value" } } ``` `toolkit_group` is the users group within this specific toolkit (resolved via `jde_associations` or `toolkit_overrides`). `db_context` contains values fetched via `inject_db_context` config. ## Client filter Validates the incoming request payload before anything else happens. ```toml [endpoints.0.client_filter] allowed_fields = ["barcode", "quantity"] required_fields = ["barcode"] max_body_bytes = 4096 ``` | Field | Notes | |-------------------------|------------------------------------------------------------------| | `allowed_fields` | only these fields are accepted, everything else gets stripped | | `required_fields` | these must be present or you get 400 | | `max_body_bytes` | max payload size | | `allowed_content_types` | restrict accepted content types | | `field_rules` | per field validation (type, max_length, pattern, allowed_values) | Per field rules example: ```toml [endpoints.0.client_filter.field_rules.barcode] type = "string" max_length = 50 pattern = "^[A-Z0-9-]+$" ``` ## Database context injection `inject_db_context` lets you pull values from the database and include them in the request context. Simple: pull a value by column name ```toml inject_db_context = ["users.email"] ``` Filtered: pull specific rows based on payload values ```toml inject_db_context = ["items.name?id=$payload.item_id"] ``` The `$payload.field` syntax references fields from the clients request body. ## Overwrite wrapping Modify the context envelope before sending it to the backend. - prefix with `-` to remove a field: `"-power"` removes the power level from context - without prefix: promotes a db_context value to a top level field ## Success response ```json { "success": true, "request_id": "abc123", "endpoint": "/tk/app/beepzone/kiosk/scan", "data": { ... } } ``` ## Error responses | Code | When | |------|-----------------------------------------------------------| | 400 | payload validation failed | | 401 | no token or invalid session | | 403 | endpoint permission denied | | 404 | toolkit not found/disabled, endpoint path doesnt exist | | 500 | internal error, DB context fetch failed, executable error | | 502 | HTTP upstream returned an error |