# HTTP Requests Call external APIs from your workflow using the `HTTPRequest` action and route the process based on responses using the `CheckParameter` condition. This pattern integrates third-party services - payment gateways, inventory systems, notification services - into your [workflow scheme](https://docs.workflowengine.io/get-started/concepts/scheme/) without custom code. With `StoreResponse` enabled, `HTTPRequest` stores the response body only. For a JSON object, target a scalar field through a dotted parameter path before applying a `CheckParameter` string comparison. ## Real-world scenario: purchase workflow An e-commerce platform processes purchases through a series of API calls. When a customer places an order, the workflow: 1. **Creates an order** with a new GUID, amount, and product ID as persistent process parameters. 2. **Charges the payment** via the payment API. This combines reservation and capture in one call. 3. **Confirms the order** when the payment response action equals the expected value; otherwise calls the cancellation endpoint. `ChargePayment` stores the JSON response as a `DynamicParameter`. The success transition reads the scalar `ChargeResult.json.action` value. `ConfirmOrder` and `CancelOrder` store their response bodies in the persistent `ConfirmResult` and `CancelResult` parameters, so the final API response remains available after the process is finalized. ## Workflow scheme The example below uses [httpbin.org](https://httpbin.org) as a mock API. Its `/post` endpoint normally returns a JSON object with the submitted request body under `json`. When that echo response is available, `CheckParameter` reads `ChargeResult.json.action` and the success path runs. In production, replace the URL and comparison with fields from your API contract. :::note This scheme is intentionally simplified for learning. In production, configure [ExceptionsHandlers](https://docs.workflowengine.io/get-started/concepts/activity/#exception-handling) for activities that call external APIs. Choose an appropriate `Retry`, `SetActivity`, or `SetState` strategy, validate the API outcome defined by its contract, and keep confirmation non-final when the workflow may still need compensation. ::: ![Purchase workflow scheme](https://docs.workflowengine.io/images/plugins/basic-plugin/http-requests/http-request.png) **Related capabilities:** `HTTPRequest` action, `CheckParameter` condition, `RequestHeaders` setting. ```xml filename="purchase-workflow.xml" ``` ## Configuration Use `RequestHeaders` on the [BasicPlugin](https://docs.workflowengine.io/plugins/basic-plugin/overview/) instance only for static default headers that are valid for every request made by the `HTTPRequest` action and the `CheckHTTPRequest` condition. ```csharp basicPlugin.RequestHeaders.Add("X-Api-Version", "2026-01-01"); ``` Do not store a request-specific Bearer token in `RequestHeaders`: the dictionary belongs to the plugin instance, not to a process, and its values are sent with every request. Set credentials on the particular action or condition through the scheme-level `Headers` parameter. Process parameter substitution is supported, for example: ```json "Headers": "Authorization=Bearer @AccessToken" ``` Prefer to expose `AccessToken` as an [external parameter](https://docs.workflowengine.io/get-started/concepts/parameter/#advanced-parameter-scenarios) through an `IWorkflowExternalParametersProvider` backed by your application's credential storage instead of persisting the token with the process. The engine resolves `@AccessToken` immediately before the action or condition runs. Scheme-level headers are added after the defaults. A duplicate name appends another value instead of replacing the global value, and a header that rejects multiple values can throw a `FormatException`. In your scheme, assign `HTTPRequest` to an [activity](https://docs.workflowengine.io/get-started/concepts/activity/) Implementation. Configure the URL, method (GET/POST), request body, and optionally store the response body in a process [parameter](https://docs.workflowengine.io/get-started/concepts/parameter/). On an outgoing [transition](https://docs.workflowengine.io/get-started/concepts/transition/), use the `CheckParameter` condition to inspect a scalar value and route the process. For an undeclared response parameter, `HTTPRequest` parses valid JSON into a scalar value, `List`, or `DynamicParameter`. Non-JSON text remains a string. If the target parameter has a declared type, `HTTPRequest` deserializes the body to that type. JSON object fields are available through dotted paths, so the example compares `ChargeResult.json.action` with `ChargePayment` by using `Equal`. `StoreResponse` does not store the HTTP status code or response headers. The parameter contains only the parsed response body. ## Enums The following enums control how HTTP requests are formatted and how responses are validated. ### ContentType The `ContentType` parameter in `HTTPRequest` specifies the request body format for POST requests. | Value | Format | |-------|--------| | `Urlencoded` | `application/x-www-form-urlencoded` - form data encoded as name/value pairs (e.g. `Name=Value;`). | | `Json` | `application/json` - request body encoded as JSON. | ### CompareType The `CompareType` parameter in `CheckHTTPRequest` and `CheckParameter` determines how the selected response value is evaluated. | Value | Example | |-------|---------| | `Equal` | n == v | | `NotEqual` | n != v | | `Contains` | "yummy" contains "umm" | | `NotContains` | "yummy" does not contain "yy" | | `StartWith` | "yummy" starts with "yu" | | `EndWith` | "yummy" ends with "my" | | `NotStartWith` | not "yummy" starts with "yy" | | `NotEndWith` | not "yummy" ends with "um" | | `StartAndEndWith` | "yummy" starts and ends with "y" | | `NotStartAndEndWith` | "yummy" does not start or end with "mm" | | `Greater` | n > v | | `Less` | n < v | | `GreaterOrEqual` | n >= v | | `LessOrEqual` | n <= v | | `In` | 5 in (1, 2, 3, 4, 5) | | `NotIn` | 6 not in (1, 2, 3, 4, 5) | ## See also - [Basic Plugin Overview](https://docs.workflowengine.io/plugins/basic-plugin/overview/): Registration, actions, conditions, rules, and common configuration. - [Sending Emails](https://docs.workflowengine.io/plugins/basic-plugin/sending-emails/): Send email notifications at workflow stages. - [Managing Parameters](https://docs.workflowengine.io/plugins/basic-plugin/managing-parameters/): Store, remove, and branch on parameter values. ## Frequently asked questions **How do I add authentication headers to HTTP requests?** Set the scheme-level `Headers` parameter on the particular `HTTPRequest` action or `CheckHTTPRequest` condition. It can reference a process parameter, for example `Authorization=Bearer @AccessToken`; prefer to supply the token through an `IWorkflowExternalParametersProvider`. Do not put a request-specific Bearer token in the plugin-wide `RequestHeaders` dictionary because its value is shared by every request. Also avoid duplicating a global header name: the local value is appended rather than replacing it and may be rejected when the header does not support multiple values. **How do I check the response from a previous API call?** Use the `CheckParameter` condition on the transition leaving the activity. Set `ParameterName` to the name you used in `ParameterName` on the `HTTPRequest` action, or use a dotted path such as `ChargeResult.json.action` for a JSON object. Choose a `CompareType` and provide the scalar `Value` to match. An undeclared response parameter stores parsed JSON data, while non-JSON text remains a string. **What happens if the HTTP request fails?** The `HTTPRequest` action throws when `HttpClient` reports a transport failure, timeout, or cancellation. It does not convert a non-2xx status into an exception, but `StoreResponse` saves only the response body. The stored parameter does not expose the status code or response headers; use a custom action or an outcome field in the response body when routing requires that metadata. **Why use CheckParameter instead of CheckHTTPRequest?** `CheckHTTPRequest` makes an additional HTTP request to evaluate the condition - it does not reuse the response stored by the `HTTPRequest` action. For idempotent GET requests this is fine, but for POST requests (which change server state) you must use `CheckParameter` to check the previously stored response. This avoids sending the same state-changing request twice.