External API Calls from Workflows
Overview
The web_request action lets customers wire their workflows into external systems. A typical use
is checking a loyalty point balance in the customer's own CRM, storing the returned value as a
user attribute, and then sending a message containing it.
This work runs under its own profile (SVC=web-request-worker) because the destination is a
customer-operated API that may be slow or down, and it must not be allowed to drag down the main
action queue.
Business Flow
- Receive the same
ActionExecutePayloadused by action_execute, but withactionType = web_request. - Read
WebRequestActionConfigfromactionConfig: method, url, headers, body,responseMappings,postAction, and the retry and timeout settings. - Resolve merge tags in the url, headers, and body. The
{{...}}syntax draws from three sources:- system attributes, via
systemattribute.Service, which caches them in Redis line_userfields andcustom_attributevalues- the
userIddirectly
- system attributes, via
- Fire the HTTP request with retries
- the default timeout is 30,000 ms (
defaultTimeoutMs) - up to three attempts (
defaultRetryMaxAttempts), with backoff starting at 1,000 ms - errors are classified explicitly:
clientErrorfor 4xx responses, which are not retried, andserverErrorfor 5xx responses, which are retried and exposeStatusCode()so the mq layer can treat them as transient
- the default timeout is 30,000 ms (
- Map the response back through
processResponseMappings, where each mapping uses JSONPath to extract a value from the response and write it to a destination.- destinations can be a system attribute or a user attribute (
line_user.custom_attribute) - the
{{value}}template is supported for composing new values - a single failing mapping does not fail the whole job
- destinations can be a system attribute or a user attribute (
- postAction — when configured, a new
ActionExecutePayloadis assembled and published toaction_executeto continue the chain, for instance sending a message containing the points just retrieved. This is how workflows are chained together. onError— if the configuration defines an error branch, that path is taken instead.
Key Files & Functions
internal/webrequest/service.goService.Execute(ctx, payload)— the entry point, withexecute()holding the real flowexecuteWithRetry(),doRequest(),onError()processResponseMappings(),processOneMapping()resolveMergeTags(),resolveHeaderMergeTags(),getLineUser()- the error types
clientError,serverError(which has aStatusCode()method), andstatusError - the constants
defaultTimeoutMs = 30000,defaultRetryMaxAttempts = 3, anddefaultRetryBackoffMs = 1000
internal/webrequest/consumer.go—Consumer.HandleWebRequestinternal/webrequest/config.go— theWebRequestActionConfigandResponseMappingstructsinternal/webrequest/jsonpath.go— the JSONPath implementation, matching thejsonpath-plusbehaviour of the legacy systeminternal/systemattribute/systemattribute.go— reads and writes system attributes, cached in Rediscmd/worker/main.go—runWebRequestWorker()- Queue: consumes
web_request_executeand publishesaction_execute(profileweb-request-worker)
Connections to Other Services
- Receives jobs from: the Trigger / Workflow Automation Engine, whose
executeActionroutes to this queue wheneverrule.actionTypeequalsweb_request - Tables:
line_user(both as a merge tag source and as the write target forcustom_attribute), plussystem_attributeandattribute_master - Redis: the system attribute cache
- External HTTP: the customer's API, using the method, url, and headers from the configuration
- RabbitMQ: publishes to
action_executefor postAction - This job never calls the LINE API directly — message delivery happens in the postAction, via the action executor