Endpoints
An endpoint is a route through the Manager's Enterprise Service Bus (ESB). A machine user calls a path on the Manager; the Manager authenticates the caller, optionally transforms the body with a Go template, adds backend credentials, forwards the request to your backend URL, and writes an audit row. Use endpoints when external systems or automation must reach your backends through one authenticated, audited gateway.
Endpoints belong to an application. Machine users belong to an environment.
Where endpoints live
Open a project, then the application, then Endpoints in the sidebar (/<project>/applications/<app>/endpoints). Any project member can view the page; creating, editing and deleting endpoints needs the project role maintainer or owner (or the system administrator role).
The list shows Name, URL (the backend target), Input Type, Output Type, Status (Enabled / Disabled) and Actions (View Details, Edit, Delete). Deleting asks for confirmation and cannot be undone.
Creating an endpoint
- Click Create Endpoint.
- Fill in the Create Endpoint dialog:
| Field | Notes |
|---|---|
| Name (required) | Up to 100 characters. |
| Description | Free text. |
| ESB Consume URL (required) | The inbound path that selects this endpoint, e.g. /api/webhook. Must start with /, must not be an absolute URL, must not contain .. or whitespace. Up to 500 characters. |
| Endpoint URL | The backend address to forward to, e.g. https://backend.example.com/webhook. Must be absolute http or https with a host. Optional; up to 500 characters. |
| Input Message Type / Output Message Type | SOAP, XML or JSON; both can be left unset (see Message types). |
| Authentication Type | None (default), Basic or Bearer. Basic shows Username and Password; Bearer shows Bearer Token. Passwords and tokens are encrypted at rest. |
| Log Level | None, Basic (default) or Full. See Audit log level. |
| Transformation Template | A Go text/template. See Message transformation. |
| Test this template | Expandable preview. Available only when editing a saved endpoint. |
| Enabled | Toggle; new endpoints default to enabled. |
- Click Save.
The same dialog opens as Edit Endpoint from the list or from the detail page's Edit button.
The endpoint page
Click View Details to open /<project>/applications/<app>/endpoints/<endpointId>. Endpoint Information shows Name, Status, Description, ESB Consume URL, ESB Invocation Path (the full path callers use), Endpoint URL, Input/Output Message Type, Authentication Type, Transformation Template, Created at and Created by.
Below it, Machine Users lists which machine users may call this endpoint (see Machine user access).
Calling an endpoint
The ESB accepts any HTTP method at:
/esb/<applicationId><consumeURL>For example, an endpoint with consume URL /api/webhook in application 3f2b… is called at POST /esb/3f2b…/api/webhook. The request must carry the machine user's token as Authorization: Bearer <token> (the ESB accepts Bearer tokens only), and the endpoint must be Enabled with an enabled access row for that machine user; otherwise the ESB answers 404 Endpoint not found or not enabled. Repeated failed authentications are throttled with 429 too many failed authentication attempts; retry later and a Retry-After header.
Limits (Manager config keys under esb:): request bodies are capped at max_request_bytes (default 10 MiB), upstream responses at max_response_bytes (default 10 MiB), and the forward times out after forward_timeout (default 30s).
See the ESB documentation for the full request flow and error responses.
Machine user access
Access is a per-(machine user, endpoint) row with its own enabled flag.
- On the endpoint page, click Add Machine User.
- Pick a Machine User and leave Enabled on.
- Click Add Access.
Each row in the table has an enabled toggle and a Remove Access action. Machine users are created per environment on the Machine Users page; see Machine Users.
ESB audit log level
Every call through an endpoint can write one ESBAuditLog row. The endpoint's Log Level decides how much:
| Level | What is stored |
|---|---|
| None | Nothing. |
| Basic (default) | Timestamp, endpoint, application, machine user, source IP, method, path, target URL, response status, duration, and whether a transformation was applied. No headers, no bodies. |
| Full | Everything in Basic plus request and response headers and bodies. Sensitive headers and body fields are redacted before storage. |
Database growth
Full logging stores every request and response body. Use it while debugging or where compliance requires it, then switch back to Basic.
Message transformation
If Transformation Template is set, the ESB parses the incoming body, renders the template with the context below, and forwards the rendered text instead of the original body. Without a template the body is forwarded unchanged.
Template context
.Data: the parsed request body (JSON object, or decoded XML/SOAP). If the body could not be parsed as JSON and no input type is set,.Datais{"Body": "<raw text>"}..Application.ID,.Application.Name,.Application.Slug,.Application.Description.Endpoint.ID,.Endpoint.Name,.Endpoint.ConsumeURL,.Endpoint.URL,.Endpoint.Description.User.ID,.User.Username,.User.Name: the calling machine user.Meta.Timestamp(RFC 3339 string),.Meta.RequestTime(Gotime.Time).Env: a map of the allow-listed environment variablesPRODUCTIFY_ENV,PRODUCTIFY_REGION,APP_ENV,DEPLOYMENT_ENV. Nothing else is readable.
Template functions
| Function | Result |
|---|---|
toJson | Value as a JSON string |
jsonEscape | Value as a JSON string without surrounding quotes, for safe embedding inside "..." |
toString | Value as a string |
toUpper / toLower | Upper- or lower-case string |
now | Current time, RFC 3339 |
env "KEY" | The environment variable, only for the four allow-listed keys; anything else is "" |
Any other function name is a template parse error.
Example
{
"endpoint": "{{ .Endpoint.Name }}",
"timestamp": "{{ .Meta.Timestamp }}",
"user": "{{ jsonEscape .User.Username }}",
"environment": "{{ .Env.PRODUCTIFY_ENV }}",
"data": {{ .Data | toJson }}
}Rename fields:
{
"customerName": "{{ .Data.name | toUpper }}",
"customerEmail": "{{ .Data.email | toLower }}",
"receivedAt": "{{ now }}"
}Convert XML to JSON: set Input Message Type to XML and Output Message Type to JSON, then:
{ "converted": {{ .Data | toJson }}, "processedAt": "{{ now }}" }Testing a template
On a saved endpoint, open Edit Endpoint, expand Test this template, paste a Sample request body and click Run preview. The Manager renders the template on the server with the endpoint's real context and shows Rendered output and its content type. Nothing is forwarded and nothing is saved. The API equivalent is previewESBTransform(endpointId, input: { body, transformationTemplate }); transformationTemplate is optional and lets you try an unsaved candidate.
Input and output message types
Input Message Type controls how the body is parsed into .Data:
| Setting | Parsing |
|---|---|
JSON | json.Unmarshal; a parse failure is an error |
XML or SOAP | XML decoded to a map |
| unset | Try JSON; on failure .Data becomes {"Body": "<raw text>"} |
Output Message Type sets the Content-Type sent to the backend when a template is applied: JSON → application/json, XML → application/xml, SOAP → text/xml; charset=utf-8, unset → application/json.
API
mutation {
createEndpoint(
applicationId: "app-uuid"
input: {
name: "Order webhook"
description: "Forwards orders to the ERP"
consumeURL: "/orders"
url: "https://erp.example.com/api/orders"
authType: Bearer
authToken: "erp-token"
inputMessageType: JSON
outputMessageType: JSON
logLevel: BASIC
enabled: true
}
) {
id
name
consumeURL
}
}createEndpoint(applicationId: ID!, input: CreateEndpointInput!),updateEndpoint(id: ID!, input: UpdateEndpointInput!),deleteEndpoint(id: ID!).deleteEndpointis refused once the endpoint has served logged ESB traffic: the ESB audit trail is append-only and its rows carry aNOT NULLreference to the endpoint, so the refusal names the count and points at the only remedy,updateEndpointwithenabled: false. The same applies one level up todeleteApplication, since an application whose endpoints all carry ESB rows cannot be emptied.- Input fields:
name,description,enabled,consumeURL,url,inputMessageType/outputMessageType(SOAP | XML | JSON),authType(Basic | Bearer | None),authUsername,authPassword,authToken,transformationTemplate,logLevel(NONE | BASIC | FULL). - Queries:
endpoint(application: ID!, id: ID!)andendpoints(application: ID!, filters, order, pagination); both need membership of the application's project (or the systemadministratorrole). - Access rows:
createMachineUser2Endpoint,updateMachineUser2Endpoint,deleteMachineUser2Endpoint; list withmachineUser2endpoints(endpoint: ID!, ...). - Audit trail:
esbAuditLogs(applicationId: ID!, endpointId: ID, limit: Int).
See the API Reference.
Troubleshooting
404 Endpoint not found or not enabled
The endpoint is disabled, the consume URL does not match the path after /esb/<applicationId>, or the calling machine user has no enabled access row.
Backend authentication fails
Check Authentication Type and the stored credential; rotate the token or password in Edit Endpoint.
Transformation errors
- Check
syntax and use only the functions listed above. - Make sure the Input Message Type matches what the caller sends; a JSON parse failure with
JSONset is an error. - Use Test this template with a real sample body, or temporarily set Log Level to
Fulland read the request body from the ESB audit trail.