Web service automations
How a web service automation turns an APIANT automation into a synchronous HTTP endpoint that returns a status and body to the caller, including CORS, error responses and the absence of automatic retries.
A web service automation is an HTTP endpoint backed by an automation. The caller sends a request to the automation's URL, the automation runs while the caller waits, and the caller receives the HTTP status and body the automation sets. A webhook trigger, by contrast, accepts the request and runs the automation in the background.
Build a web service
Describe the endpoint, including its inputs and what it returns, for example: "Build a web service that takes an email query parameter, looks the contact up in HubSpot, and returns their company name as JSON, or a 404 if there is no match."
A web service automation uses the two operations of the Web Service app:
- HTTP request received (instant), the trigger.
- The steps that do the work.
- Return HTTP response, which sets what the caller receives.
When the automation is committed, Claude or the assistant returns the web service URL. It has this shape:
https://hooks.apiant.ai/webservice-YOUR_WEB_SERVICE_ID
YOUR_WEB_SERVICE_ID stands for the identifier Claude or the assistant gives you; use the full URL exactly as returned. Each web service automation has its own URL. Turn the automation on before calling it.
Request data
The URL accepts GET, POST, PUT and HEAD. The trigger exposes the request to later steps:
| Field | Contents |
|---|---|
trigger.params.<name> | One query parameter |
trigger.body.<field> | One field of a JSON body, parsed automatically |
trigger.body | The raw body, when it is not JSON |
trigger.path, trigger.query_string, trigger.content_type | The request path, the raw query string and the content type |
The trigger's Query parameters and POST payload example settings document the endpoint's contract for people reading the automation. The platform does not use them to parse the request: every query parameter and JSON field is available whether or not it is listed.
The response
Return HTTP response has three inputs:
| Input | Default | Notes |
|---|---|---|
| HTTP status code | 200 | A whole number from 100 to 599. Other values are refused when the automation is saved, or when the step runs if the value comes from a mapping. |
| Response data | Empty | The body, as text. To return JSON, build the JSON text in the mapping or in a script step. |
| Content type | text/plain; charset=utf-8 | Set application/json when returning JSON |
Put Return HTTP response at the end of every branch that can finish the run. If more than one runs, the last one sets the response. If none runs, the caller receives an empty 200.
Keep the automation short, such as one lookup or one API call and the response. For long work, return 202 with an ID and continue in a separate webhook automation.
Errors the caller can receive
| Status | Body | Cause |
|---|---|---|
404 | not found or web service not found | The URL is wrong or the automation was deleted |
429 | monthly usage limit reached | The account reached its monthly web service call or task limit |
500 | The step's error message | A step failed. The run stops and the error is returned. |
500 | web service did not return a synchronous response | The automation paused (for example on a snooze, form or approval step) or was halted instead of finishing |
503 | web service is not active | The automation is off |
Error responses are plain text. To return a clean error of your own, such as a 404 with a message, ask Claude to add a condition that ends in Return HTTP response with that status.
No automatic retries
A failed web service run is not retried and is not queued for later. The caller is waiting, so the calling system decides whether to send the request again.
Calling from a browser
Web service responses, including error responses, carry Access-Control-Allow-Origin: *, and the URL answers OPTIONS preflight requests. JavaScript on your own site can send a JSON POST and read the reply with no configuration. The endpoint does not allow credentialed requests (cookies); the URL is the only credential. Because anyone who sees the page can see the URL, never return data in a web service response that a visitor to that page must not see.
const res = await fetch("https://hooks.apiant.ai/webservice-YOUR_WEB_SERVICE_ID", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: "jordan@example.com" }),
});
const data = await res.json();
Testing
A test run from Claude or the assistant runs the automation's steps but does not go through the URL. To test the real endpoint, turn the automation on and send a request from your own tools. Claude or the assistant can give you a ready-made request built from the trigger settings.
$ curl -X POST "https://hooks.apiant.ai/webservice-YOUR_WEB_SERVICE_ID" \
-H "Content-Type: application/json" \
-d '{"email":"jordan@example.com"}'
Usage
Each call counts against your plan's monthly web service call limit and also consumes tasks. See Plans, usage and billing.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
503 web service is not active | Turn the automation on. |
| A step does not receive a query parameter or JSON field value | The request did not include that parameter, or the mapping uses the wrong prefix. Query parameters are trigger.params.<name>; JSON fields are trigger.body.<field>. |
| A strict client rejects the JSON response | Content type is empty, so the response is text/plain. Set it to application/json. |
| The caller times out | The automation does too much work in the request. Shorten it or return 202 and continue elsewhere. |
| The response comes from the wrong branch | More than one Return HTTP response ran. Keep one per branch, at its end. |