Skip to content
This page View Markdown Open in ChatGPT Open in Claude

Call external API

Makes HTTP calls to any URL from the server : one call, or a list of calls run in parallel or one after the other, with preProcess and postProcess rules which copy a value of one answer into the request of another.

Method POST
URL /api/system-api/admin/call-external-api : admin is the user path of your account
Body one call, an array of calls, or { type: "parallel" | "sequential", data: [ … ] }
Answer data : the response of the call, { statusCode, headers, body, … }, or an array of them
From code g.sys.system.callExternalApi

One call

Body
{
    "url": "https://api.example.com/customers",
    "method": "POST",
    "timeout": 5000,
    "headers": { "authorization": "Bearer …" },
    "queryParams": { "select": "first_name" },
    "body": { "first_name": "James", "last_name": "Bond" }
}
Answer
{ "success": true, "statusCode": 200, "data": { "statusCode": 201, "headers": { "content-type": "application/json" }, "body": { "id": 42, "first_name": "James" } } }
Key Meaning
url Required. The full URL.
method GET (default), HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH.
timeout Milliseconds.
headers, queryParams, body What to send.
id A name for this call, used by preProcess and postProcess of other calls.
preProcess, postProcess Rules { from, to } run before and after the call : from is a path starting with the id of a call (saveApi.output.body.data.id), to a path in a call (setApi.body.customerId).
output Filled with the answer of the call, for the rules of the others.
  • The answer of a call is the response object of the HTTP client (undici) : statusCode, headers, and body parsed as JSON. A body which is not JSON comes as text.

In parallel, in sequence

Body : a save, then two calls at once with its result
[
    { "id": "saveApi", "url": "https://api.example.com/customers", "method": "POST", "body": { "first_name": "James" },
      "postProcess": [ { "from": "saveApi.output.body.id", "to": "setApi.body.customerId" } ] },
    { "type": "parallel", "data": [
        { "id": "setApi", "url": "https://api.example.com/preferences", "method": "PUT", "body": {} },
        { "id": "notify", "url": "https://hooks.example.com/new-customer", "method": "POST", "body": { "source": "shop" } }
    ] }
]
  • The top level array runs in sequence ; type: "parallel" runs its data at once, type: "sequential" one after the other. Groups nest.
  • The answer is an array with one entry per call, nested like the body.

From code

const resp = await g.sys.system.callExternalApi<{ id: number }>({ url: 'https://api.example.com/customers/42' });
if (resp.statusCode === 200) g.logger.log(resp.body.id);
  • Custom APIs can also use any HTTP client of npm from the sandbox ; this API adds the parallel and sequential plans and the data copying without code.

Access and settings

  • Over HTTP, a system API answers once its settings give it apiAccessType: TOKEN_ACCESS (the token of an API user whose group grants this system API, in x-am-authorization) or IS_PUBLIC. Without settings it is NO_ACCESS : your code calls it through g.sys, the admin panel tests it, and an HTTP call is refused.
  • The settings can also cache the answer or require person tokens (authProviders) ; pre and post hooks run around it like around any API.
  • The request headers apply : x-am-response-case, x-am-content-type-response, x-am-internationalization, x-am-tenant-username…

Errors

Code When
400 The body is wrong : the message names the missing or invalid key, or a url which is not valid.
401 No valid API user token, or the API is NO_ACCESS : You are not authorized to access this API.
403 No group grants this system API.