HTTP Destination
Send messages to an HTTP/REST endpoint with configurable authentication, retry policies, and TLS.
Overview
The HTTP destination delivers processed messages to any HTTP or REST endpoint via standard HTTP methods. It supports multiple authentication schemes, custom headers, configurable timeouts, TLS settings, and a flexible retry policy with backoff strategies. This is the most common destination type for integrating with FHIR servers, EHR APIs, cloud services, and third-party webhooks.
Configuration
Define an HTTP destination in your root intu.yaml under the destinations key:
# intu.yaml
destinations:
fhir-server:
type: http
http:
url: https://fhir.hospital.org/fhir/R4
method: POST
headers:
Content-Type: application/fhir+json
X-Correlation-Id: ${messageId}
timeout_ms: 30000
auth:
type: bearer
token: ${FHIR_ACCESS_TOKEN}
tls:
insecure_skip_verify: false
ca_cert: /etc/ssl/certs/hospital-ca.pem
retry:
max_attempts: 5
backoff: exponential
initial_delay_ms: 500
max_delay_ms: 30000
jitter: true
retry_on: [500, 502, 503, 504]
no_retry_on: [400, 401, 404, 422]
Properties
Core Properties
${VAR} syntax.GET, POST, PUT, PATCH, DELETE. Defaults to POST.30000 (30 seconds).Authentication
The auth object configures request authentication. The type field determines which auth strategy is used.
basic, bearer, api_key, oauth2.Basic Auth
auth:
type: basic
username: ${HTTP_USER}
password: ${HTTP_PASS}
Bearer Token
auth:
type: bearer
token: ${ACCESS_TOKEN}
API Key
auth:
type: api_key
header: X-API-Key
key: ${API_KEY}
OAuth2 Client Credentials
auth:
type: oauth2
token_url: https://auth.hospital.org/oauth/token
client_id: ${OAUTH_CLIENT_ID}
client_secret: ${OAUTH_CLIENT_SECRET}
scopes:
- system/Patient.write
- system/Encounter.write
TLS
false. Use only in development environments.Retry Policy
3.constant, linear, exponential. Defaults to exponential.1000.60000.true.[500, 502, 503, 504].retry_on.Full Example
A complete configuration that receives HL7v2 ADT messages via TCP/MLLP, transforms them to FHIR Patient resources, and posts them to a FHIR R4 server.
Root Configuration
# intu.yaml
destinations:
fhir-r4-server:
type: http
http:
url: https://fhir.hospital.org/fhir/R4/Patient
method: POST
headers:
Content-Type: application/fhir+json
Accept: application/fhir+json
timeout_ms: 15000
auth:
type: oauth2
token_url: https://auth.hospital.org/oauth/token
client_id: ${FHIR_CLIENT_ID}
client_secret: ${FHIR_CLIENT_SECRET}
scopes:
- system/Patient.write
retry:
max_attempts: 5
backoff: exponential
initial_delay_ms: 500
max_delay_ms: 30000
jitter: true
retry_on: [500, 502, 503, 504]
Channel Configuration
# channels/adt-to-fhir/channel.yaml
name: adt-to-fhir
description: Transform HL7v2 ADT messages to FHIR Patient resources
source:
type: tcp
tcp:
port: 6661
mode: mllp
destinations:
- fhir-r4-server
Destination Transformer
// channels/adt-to-fhir/transformer.ts
import { Message, Context } from "@intu/sdk";
export default function transform(msg: Message, ctx: Context): Message {
const hl7 = msg.body;
const pid = hl7.segments?.find((s: any) => s.name === "PID");
if (!pid) {
ctx.logger.error("No PID segment found in ADT message");
throw new Error("Missing PID segment");
}
const patient = {
resourceType: "Patient",
identifier: [
{
system: "urn:oid:2.16.840.1.113883.4.1",
value: pid.fields[3]?.components[0] ?? "",
},
],
name: [
{
family: pid.fields[5]?.components[0] ?? "",
given: [pid.fields[5]?.components[1] ?? ""],
},
],
gender: mapGender(pid.fields[8]?.components[0]),
birthDate: formatDate(pid.fields[7]?.components[0]),
address: [
{
line: [pid.fields[11]?.components[0] ?? ""],
city: pid.fields[11]?.components[2] ?? "",
state: pid.fields[11]?.components[3] ?? "",
postalCode: pid.fields[11]?.components[4] ?? "",
},
],
};
return {
...msg,
body: patient,
headers: {
...msg.headers,
"content-type": "application/fhir+json",
},
};
}
function mapGender(code: string | undefined): string {
switch (code) {
case "M": return "male";
case "F": return "female";
case "O": return "other";
default: return "unknown";
}
}
function formatDate(raw: string | undefined): string | undefined {
if (!raw || raw.length < 8) return undefined;
return `${raw.slice(0, 4)}-${raw.slice(4, 6)}-${raw.slice(6, 8)}`;
}
no_retry_on are immediately treated as permanent failures. Ensure your FHIR server
returns appropriate status codes so that validation errors (422) are not retried.
.env and reference them with ${VAR} syntax
to keep credentials out of version control.