# Connect Frends to Atlas Labs

> To connect Frends to Atlas Labs, add a `Frends.HTTP.Request` Task to a Process for calls and an **HTTP Trigger** to receive events; the key goes in the Task's Headers list, read from an Environment Variable. Frends' OpenAPI import publishes your own API and does not generate a client for Atlas Labs, so the Task is the way in.

Canonical: `https://automationatlas.io/labs/docs/tools/frends/` · Checked: `2026-10-15`

Atlas Labs is a fictional company's API; every figure in every response is simulation data.

> **Verification level: written from Frends' Task and Trigger documentation (checked `15 Oct 2026`), not run in a Frends tenant.** Not verified: whether the Task's **Token** option adds the word Bearer for you, the header name Frends uses for its own API keys, how an HTTP Trigger Process returns its response, Process-level retry, and the expression syntax for reading one header out of `#trigger.data.httpHeaders` or decoding the Base64 body. Each is flagged where it matters below.

*Reference table — Atlas Labs API fields and Frends' documented names, not part of the fictional simulation.*

| At a glance | Value |
| --- | --- |
| Call the API | Task `Frends.HTTP.Request` `v1.13.0` (Frends `5.7`+, Crossplatform agent, `net8.0`) |
| Receive events | **HTTP Trigger** on a Process, published to an Agent Group with a public `https://` URL |
| Where the key goes | Headers list: Name `Authorization`, Value `Bearer lab_off_YOUR_KEY`, referenced from a secret Environment Variable. Alternative: Options → Authentication → **Token** |
| Body | **Message** = your JSON; Headers item `Content-Type: application/json`; ResultMethod **JToken** to read the envelope |
| `Idempotency-Key` | A Headers item set to the `webhook-id` request header from `#trigger.data.httpHeaders` (it equals the event `id`); with the unparsed Base64 option on, the body's `id` is reachable only after decoding |
| Raw body for HMAC | Trigger option “Pass content to Process as unparsed, Base64 encoded byte array” → `#trigger.data.httpContentBytesInBase64` |
| Trigger authorisation | Atlas Labs can send no Frends credential, so the endpoint needs a public policy; verify the Standard Webhooks signature in the Process instead |
| Retries | None on the Task (Options hold timeouts, redirects and protocol versions only) |
| OpenAPI import | For hosting your own API in API Management (OpenAPI `3.0.x`, `2.0` legacy), not for calling Atlas Labs |

> **Start a sandbox and your keys are filled in for you.** This page uses `lab_off_YOUR_KEY` and `lab_fac_YOUR_KEY`. After you [start a sandbox](https://automationatlas.io/labs/#start-sandbox-heading), the “Connect it” panel's curl tab gives you the exact header values to paste into Environment Variables.

- Atlas Labs → Your Process: signed webhook, to the HTTP Trigger
- Your Process → Atlas Labs: Frends.HTTP.Request, Bearer key
- Your Process → Your systems: next shape

Both legs are optional: a Process can only listen, only call, or do both.

## How do I call Atlas Labs from a Process?

1. **Add a Task shape and choose `Frends.HTTP.Request`** (Task package “Request” in the HTTP group). Older `Frends.Web` tasks in legacy Processes are different.
2. **Fill the Input.** This example bridges an accepted sales order into a Factory work order; read `quantity` and `due_sim_day` first with a `GET https://automationatlas.io/labs/api/v1/office/sales-orders/<id>` using the Head Office key.
   - Method: `POST`
   - Url: `https://automationatlas.io/labs/api/v1/factory/work-orders`
   - Message: `{"sales_order_id": "<sales_order_id from the decoded body>", "quantity": <from the order>, "due_date": <due_sim_day from the order>}`
   - ResultMethod: JToken
   - Headers: `Content-Type: application/json`; `Authorization: Bearer lab_fac_YOUR_KEY`; `Idempotency-Key:` the `webhook-id` header from `#trigger.data.httpHeaders` (= the event `id`)
   **Preset matters.** Pick a preset with a manual bridge (Standard or Full) or this write returns `409 already_bridged`, because Starter bridges automatically.
3. **Keep the key in a Frends Environment Variable** marked secret and reference it in the header value; never hard-code it in the Process. Alternatively use Options → Authentication → **Token**, which the docs describe as a bearer token added as the Authorization header; whether it prefixes `Bearer ` for you is not stated plainly, so the Headers list is the unambiguous route.
4. **Options:** ConnectionTimeoutSeconds defaults to `30` and FollowRedirects to true. Atlas Labs never redirects and answers quickly, so the defaults are fine.
5. **Handle failure.** ThrowErrorOnFailure defaults to true, which stops the Process on any `4xx` or `5xx`. Set it to false to read `Result.StatusCode`, `Result.Body` and `Result.Error` yourself, for example to treat `409 already_bridged` as success.

## How do I receive Atlas Labs events in Frends?

1. **Create a Process with an HTTP Trigger.** The trigger URL is the part after the Agent Group's base URL (path variables in braces); set the method to `POST` (it defaults to ANY).
2. **Authorisation.** The default is API Policy (an API key through Frends API Management, OAuth, or public). Atlas Labs sends only the Standard Webhooks headers, so choose a public policy for this endpoint and verify the signature inside the Process. Basic auth is not supported on Cloud Agents.
3. **Keep the raw bytes.** Enable “Pass content to Process as unparsed, Base64 encoded byte array”; the body then arrives in `#trigger.data.httpContentBytesInBase64` (and `httpBody` is not available). Headers are in `#trigger.data.httpHeaders`. The HMAC algorithm is on the [Webhooks page](https://automationatlas.io/labs/docs/webhooks/).
4. **Decode and parse.** Base64-decode `#trigger.data.httpContentBytesInBase64`, verify the HMAC over those exact bytes, then JSON-parse the result; only then are `id`, `type` and `data.sales_order_id` available to the Task that follows. Take the `Idempotency-Key` from the `webhook-id` entry of `#trigger.data.httpHeaders` instead, which needs no decoding. The exact expression or shape for the decode, and for reading one entry out of the headers dictionary, is not on the trigger page we read, so we have not confirmed it; use the expression form your tenant already uses.
5. **Publish the Process to an Agent Group** and subscribe its `https://` URL in Atlas Labs with either key.
   - Method: `POST`
   - URL: `https://automationatlas.io/labs/api/v1/webhooks`
   - Headers: `Authorization: Bearer lab_off_YOUR_KEY`; `Content-Type: application/json`
   - Body: `{"url": "https://<agent-group-base>/atlas-labs/events", "events": ["office.sales_order.accepted"]}`
6. **Answer within five seconds.** Atlas Labs waits `5` seconds for a `2xx` and disables the subscription after `5` consecutive failures. How a Process returns its response is not described on the trigger page we read; confirm it in your tenant, then send the test ping (`POST /webhooks/{id}/test`).

## Idempotency and retries

- The Task has no retry option. For a `429 rate_limited`, read `Retry-After` from `Result.Headers` and loop in the Process with the same `Idempotency-Key`; the wait is usually one or two seconds.
- Calls made in parallel share one key's budget, for example when Process instances overlap, so keep calls to Atlas Labs to one or two at a time: more at once only collect more `429`s, and enough of them put the key into a short cooldown.
- With the event `id` (the `webhook-id` header) as `Idempotency-Key`, a repeated call returns the original response with `Idempotency-Replayed: true`.
- Atlas Labs re-delivers a failed webhook after `10 s`, `60 s` and `300 s`; de-duplicate on the event `id`.

## Common errors

*Reference table — errors as seen from Frends, not part of the fictional simulation.*

| You see | Why, and the fix |
| --- | --- |
| `401 unauthorized` | The header value lacks `Bearer `, the Environment Variable is empty, or the key is unknown, revoked or deleted with its sandbox. An expired sandbox answers writes with `423 sandbox_expired` instead. |
| `403 wrong_system` | The wrong key for the route. `/factory/*` wants `lab_fac_`, `/office/*` wants `lab_off_`. |
| `415 unsupported_media_type` | Add the `Content-Type: application/json` Headers item. |
| Process stops on `409` | ThrowErrorOnFailure is true. Set it to false and branch on `Result.StatusCode`. |
| Subscription goes `disabled` | The trigger's authorisation refused Atlas Labs, or the Process did not answer `2xx` within `5` seconds. Fix it and re-enable with `PATCH /webhooks/{id}`. |
| `422 webhook_url_rejected` | The Agent Group URL was not public `https://` on port `443`; `details.reason` names the rule. |

## Gotchas

- **Version.** `Frends.HTTP.Request` `v1.13.0` needs Frends `5.7` or later on a Crossplatform agent.
- **OpenAPI import is for hosting.** Importing `openapi.json` into API Management publishes an API of your own; it does not create a client for Atlas Labs.
- **API Trigger vs HTTP Trigger.** An API Trigger needs an OpenAPI specification in API Management first; the HTTP Trigger is a standalone endpoint and is the simpler choice for receiving webhooks.
- **Commercial product.** We found no free tier, so the steps above were not exercised in a tenant. If you run one, tell us what to correct.

## Download

- No Process export yet — The shapes above are described from the Task and Trigger reference pages; a Process export from a real tenant is welcome. (Unknown: not run in a Frends tenant)

## Questions people ask

**Can I import the Atlas Labs OpenAPI file into Frends?** Only to host an API in API Management (OpenAPI `3.0.x`, with `2.0` for legacy). To call Atlas Labs, use the `Frends.HTTP.Request` Task.

**Which Task do I use?** `Frends.HTTP.Request` (`v1.13.0`). Its Result has `Success`, `Error`, `Body`, `Headers` and `StatusCode`.

**Where does the key go?** In the Headers list as `Authorization: Bearer lab_off_YOUR_KEY`, read from a secret Environment Variable. The Token option may do the same; we could not confirm whether it adds the Bearer prefix.

**Can the HTTP Trigger require an API key from Atlas Labs?** No. Atlas Labs sends no custom credentials, only the Standard Webhooks headers; make the endpoint public and verify the signature in the Process.

**Does the Task retry on `429`?** No. Loop in the Process using `Retry-After`, keeping the same `Idempotency-Key`.

Sources (checked `15 Oct 2026`): tasks.frends.com/tasks/Frends.HTTP.Request; docs.frends.com/tasks/tasks/http/request.md; docs.frends.com/reference/triggers/http-trigger; docs.frends.com/reference/triggers/api-trigger; Frends API specification articles (OpenAPI `3.0.1` / `2.0`). Atlas Labs facts from the API source, observed live.

[Moxo](https://automationatlas.io/labs/docs/tools/moxo/) · [Integrations hub](https://automationatlas.io/labs/docs/tools/)
