The Integration Management Engine transforms data from Irembo applications into formats required by external partner systems. It acts as a flexible middleware layer that:
An endpoint represents a specific API operation on a partner system. Each endpoint has:
When you send a request to an endpoint:
Code: COFFEE_HOT_LIST
Name: Get Hot Coffee Products
URL: https://api.sampleapis.com/coffee/hot
A mapping is a JSONata expression that defines how to transform your input data into the format expected by the partner API. The mapping must return a RequestTransformation object.
{
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"transformedField": sourceField,
"anotherField": "static value"
}
}
| Field | Description | Required |
|---|---|---|
method |
HTTP method (GET, POST, PUT, DELETE) | No |
auth |
Authentication configuration | No |
headers |
Custom HTTP headers | No |
path |
Path parameter replacements | No |
query |
Query string parameters | No |
body |
Request body (for POST/PUT) | No |
form |
Form data (for multipart requests) | No |
response |
Response transformation and validation | No |
iterateOver |
Array field name for iteration | No |
iterationCount |
Fixed number of iterations | No |
iterationResponseKey |
Key name for iteration responses | No |
Input Payload:
{
"applicantName": "John Doe",
"nationalId": "1199012345678901",
"dateOfBirth": "1990-01-01"
}
Mapping:
{
"method": "POST",
"body": {
"fullName": applicantName,
"nid": nationalId,
"dob": dateOfBirth
}
}
Result:
{
"fullName": "John Doe",
"nid": "1199012345678901",
"dob": "1990-01-01"
}
JSONata is a lightweight query and transformation language for JSON data. It allows you to select, transform, and combine data from the input payload.
// Simple field
applicantName
// Nested field
user.profile.name
// Array element
items[0].name
{
"name": applicantName,
"id": nationalId,
"fullName": firstName & " " & lastName
}
{
"status": age >= 18 ? "adult" : "minor",
"hasId": $exists(nationalId) and nationalId != ""
}
// Transform each array element
items.{
"id": itemId,
"name": itemName,
"total": quantity * price
}
// Filter array
items[price > 100]
// Sum values
$sum(items.price)
// Count elements
$count(items)
{
"upper": $uppercase(name),
"lower": $lowercase(name),
"concat": $join([firstName, lastName], " "),
"substring": $substring(text, 0, 10),
"replace": $replace(text, "old", "new")
}
{
"currentTime": $now(),
"formattedDate": $fromMillis($toMillis(dateString), "[Y0001]-[M01]-[D01]")
}
Transform data differently based on a field value:
{
"applicationType": applicationType,
"requiredDocuments": applicationType = "RENEWAL"
? ["previous_certificate", "proof_of_residence"]
: ["birth_certificate", "national_id"]
}
Convert an array of objects to a different structure:
{
"owners": BENEFICIAL_OWNERS.{
"name": ownerName,
"shares": sharePercentage,
"contact": phoneNumber
}
}
Calculate values from arrays:
{
"totalAmount": $sum(ITEMS.amount),
"itemCount": $count(ITEMS),
"averagePrice": $sum(ITEMS.price) / $count(ITEMS),
"uniqueCategories": $distinct(ITEMS.category)
}
Build nested structures from flat data:
{
"applicant": {
"personal": {
"name": applicantName,
"dob": dateOfBirth
},
"contact": {
"email": emailAddress,
"phone": phoneNumber
}
},
"application": {
"type": applicationType,
"date": $now()
}
}
You can test your JSONata expressions online:
Environment variables allow you to:
There are two ways to reference environment variables, depending on where you use them:
${VARIABLE_NAME} (String Replacement)Use this syntax outside of JSONata expressions (e.g., in simple string values):
{
"baseUrl": "${WINE_API_BASE_URL}",
"headers": {
"X-API-Key": "${API_KEY}"
}
}
This is replaced after JSONata transformation.
$."VARIABLE_NAME" (JSONata Property Access)Use this syntax inside JSONata expressions, especially in auth.parameters:
{
"auth": {
"type": "USER_CREDENTIALS",
"baseUrl": "https://api.example.com",
"parameters": {
"authPath": "/auth/login",
"method": "POST",
"bodyTemplate": {
"email": $."WINE_API_USERNAME",
"password": $."WINE_API_PASSWORD"
}
}
}
}
Important: In authentication parameters, always use $."VARIABLE_NAME" so JSONata can access the environment variables during transformation.
The timing depends on which syntax you use:
Using $."VARIABLE_NAME" (JSONata):
Using ${VARIABLE_NAME} (String Replacement):
${...} strings)${...} with actual valuesDifferent APIs require different environment variables. Here are typical examples:
# API Base URLs
COFFEE_API_BASE_URL=https://api.sampleapis.com/coffee
BEER_API_BASE_URL=https://api.sampleapis.com/beers
WINE_API_BASE_URL=https://api.sampleapis.com/wines
# Authentication Credentials
COFFEE_API_TOKEN=coffee_token_12345
BEER_API_KEY=beer_key_67890
WINE_API_USERNAME=wine_api_user
WINE_API_PASSWORD=wine_secret_password
# OAuth Configuration
OAUTH_CLIENT_ID=client_abc123
OAUTH_CLIENT_SECRET=secret_xyz789
WINE_API_USERNAME not USER)$."VARIABLE_NAME" in auth.parameters for proper JSONata evaluation${VARIABLE_NAME} for simple string replacements outside JSONata logicWrong - Using ${} in auth parameters:
{
"auth": {
"parameters": {
"bodyTemplate": {
"email": "${WINE_API_USERNAME}" // ❌ Won't work in bodyTemplate
}
}
}
}
Correct - Using $. in auth parameters:
{
"auth": {
"parameters": {
"bodyTemplate": {
"email": $."WINE_API_USERNAME" // ✓ Works correctly
}
}
}
}
{
"method": "POST",
"auth": {
"type": "USER_CREDENTIALS",
"baseUrl": "https://api.example.com",
"parameters": {
"authPath": "/auth/login",
"method": "POST",
"bodyTemplate": {
"email": $."API_USERNAME", // Use $. in auth parameters
"password": $."API_PASSWORD" // Use $. in auth parameters
}
},
"tokenConfig": {
"storageKey": "api_token",
"headerName": "Authorization",
"tokenPrefix": "Bearer",
"extractPath": "data.token"
}
},
"headers": {
"X-Client-ID": "${CLIENT_ID}", // Can use ${} in headers
"X-API-Version": "v1"
},
"body": {
"apiKey": "${EXTERNAL_API_KEY}", // Can use ${} in body
"data": {
"name": applicantName,
"timestamp": $now()
}
}
}
The engine supports multiple authentication methods:
| Type | Use Case |
|---|---|
TOKEN |
Static API token |
USER_CREDENTIALS |
Username/Password that returns a token |
CLIENT_CREDENTIALS |
OAuth 2.0 Client Credentials flow |
API_KEY |
Simple API key in header |
BASIC |
HTTP Basic Authentication |
Authentication is configured in the mapping's auth object:
{
"auth": {
"type": "TOKEN",
"parameters": { ... },
"tokenConfig": { ... }
}
}
Use when you have a long-lived API token:
{
"auth": {
"type": "TOKEN",
"parameters": {
"token": $."COFFEE_API_TOKEN"
},
"tokenConfig": {
"headerName": "Authorization",
"tokenPrefix": "Bearer"
}
}
}
Result: Adds header Authorization: Bearer your_token_here
Note: Use $."COFFEE_API_TOKEN" to access the environment variable during JSONata evaluation.
Use for username/password login that returns a token:
{
"auth": {
"type": "USER_CREDENTIALS",
"baseUrl": "https://api.sampleapis.com/auth",
"parameters": {
"authPath": "/login",
"method": "POST",
"bodyTemplate": {
"email": $."WINE_API_USERNAME",
"password": $."WINE_API_PASSWORD"
}
},
"tokenConfig": {
"storageKey": "wine_api_token",
"headerName": "Authorization",
"tokenPrefix": "Bearer",
"expiryBuffer": 300,
"extractPath": "data.access_token"
}
}
}
How it works:
https://api.sampleapis.com/auth/login with credentials from environment variables$."VARIABLE_NAME" syntax to access environment variables in bodyTemplateextractPathtokenConfig fields:
storageKey: Cache key for the tokenheaderName: HTTP header name for the tokentokenPrefix: Prefix before token (e.g., "Bearer")expiryBuffer: Seconds before expiry to refresh tokenextractPath: JSONata path to extract token from auth responseImportant: Use $."VARIABLE_NAME" in parameters.bodyTemplate to access environment variables during JSONata evaluation.
Use for OAuth 2.0 client credentials flow:
{
"auth": {
"type": "CLIENT_CREDENTIALS",
"baseUrl": "https://oauth.sampleapis.com",
"parameters": {
"authPath": "/oauth/token",
"method": "POST",
"bodyTemplate": {
"client_id": $."OAUTH_CLIENT_ID",
"client_secret": $."OAUTH_CLIENT_SECRET",
"grant_type": "client_credentials",
"scope": "read write"
}
},
"tokenConfig": {
"storageKey": "oauth_token",
"headerName": "Authorization",
"tokenPrefix": "Bearer",
"extractPath": "access_token"
}
}
}
Note: Use $."VARIABLE_NAME" for client_id and client_secret in bodyTemplate.
Use for HTTP Basic Authentication:
{
"auth": {
"type": "BASIC",
"parameters": {
"username": $."BASIC_AUTH_USERNAME",
"password": $."BASIC_AUTH_PASSWORD"
},
"tokenConfig": {
"headerName": "Authorization"
}
}
}
Result: Adds header Authorization: Basic base64(username:password)
Note: Use $."VARIABLE_NAME" syntax for username and password.
Use for simple API key authentication:
{
"auth": {
"type": "API_KEY",
"parameters": {
"apiKey": $."BEER_API_KEY"
},
"tokenConfig": {
"headerName": "X-API-Key"
}
}
}
Result: Adds header X-API-Key: your_api_key
Note: Use $."BEER_API_KEY" to access the environment variable.
You can reference values from the authentication response in your request body:
{
"auth": { ... },
"body": {
"userId": "${AUTH_RESPONSE.userId}",
"sessionToken": "${AUTH_RESPONSE.sessionToken}"
}
}
Specify the HTTP method in your mapping:
{
"method": "GET", // or POST, PUT, DELETE, PATCH
"body": { ... }
}
If not specified, the default method from the endpoint configuration is used.
Add custom HTTP headers:
{
"headers": {
"Content-Type": "application/json",
"X-Request-ID": applicationId,
"X-Timestamp": $now(),
"Accept-Language": "en-US"
}
}
Replace placeholders in the endpoint URL.
Endpoint URL: https://api.partner.com/users/{userId}/records/{recordType}
Mapping:
{
"path": {
"userId": nationalId,
"recordType": "verification"
}
}
Result: https://api.partner.com/users/1199012345678901/records/verification
Add query string parameters to the URL:
{
"query": {
"status": "pending",
"limit": "10",
"page": "1",
"sort": "date"
}
}
Result: ?status=pending&limit=10&page=1&sort=date
Transform the request body (for POST, PUT, PATCH):
{
"method": "POST",
"body": {
"applicant": {
"name": applicantName,
"nid": nationalId
},
"documents": {
"idCard": "generateAttachmentURL(NATIONAL_ID)"
}
}
}
Use form instead of body for multipart/form-data requests:
{
"method": "POST",
"form": {
"file": "getAttachmentContent(DOCUMENT)",
"fileName": DOCUMENT.fileName,
"fileType": DOCUMENT.fileType,
"applicantName": applicantName
}
}
Note: The Content-Type header is automatically set to multipart/form-data when using form.
Response transformation allows you to:
{
"method": "POST",
"body": { ... },
"response": {
"transform": {
// JSONata expressions to transform response
},
"validation": {
"successCondition": false, // JSONata boolean expression
"failureCondition": false, // JSONata boolean expression
"successTransform": {
// Transform for successful responses
},
"errorMapping": {
"code": "ERROR_CODE",
"message": "Error message",
"exception": "EXCEPTION_TYPE"
}
}
}
}
Transform the API response to extract specific fields:
API Response:
{
"status": "success",
"data": {
"beerId": "123",
"name": "IPA",
"rating": 4.5,
"metadata": {
"brewery": "Sample Brewery",
"location": "Portland"
}
}
}
Mapping:
{
"method": "GET",
"response": {
"transform": {
"id": "data.beerId",
"beerName": "data.name",
"rating": "data.rating",
"brewery": "data.metadata.brewery"
}
}
}
Transformed Response:
{
"id": "123",
"beerName": "IPA",
"rating": 4.5,
"brewery": "Sample Brewery"
}
Use boolean expressions to determine if a response represents success or failure:
Example 1: Check Status Code
{
"method": "POST",
"body": { ... },
"response": {
"validation": {
"successCondition": "status = 'success' and $exists(data.id)",
"failureCondition": "status = 'error' or status = 'failed'"
}
}
}
Example 2: Check HTTP Status in Response
{
"response": {
"validation": {
"successCondition": "statusCode >= 200 and statusCode < 300",
"failureCondition": "statusCode >= 400"
}
}
}
Example 3: Check for Specific Success Indicator
{
"response": {
"validation": {
"successCondition": "result.success = true and $exists(result.data)",
"failureCondition": "result.success = false or $exists(error)"
}
}
}
Transform successful responses differently:
API Response (Success):
{
"status": "success",
"result": {
"wineId": "W456",
"name": "Cabernet Sauvignon",
"vintage": 2018,
"price": 45.99
}
}
Mapping:
{
"method": "POST",
"body": { ... },
"response": {
"validation": {
"successCondition": "status = 'success'",
"successTransform": {
"wineId": "result.wineId",
"wineName": "result.name",
"year": "result.vintage",
"cost": "result.price",
"formattedPrice": "'$' & $string(result.price)"
}
}
}
}
Transformed Success Response:
{
"wineId": "W456",
"wineName": "Cabernet Sauvignon",
"year": 2018,
"cost": 45.99,
"formattedPrice": "$45.99"
}
Map partner API errors to your standardized error format:
API Response (Error):
{
"status": "error",
"errorCode": "INVALID_BEER_ID",
"errorMessage": "The specified beer ID does not exist",
"details": {
"beerId": "999",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Mapping:
{
"method": "GET",
"response": {
"validation": {
"failureCondition": "status = 'error'",
"errorMapping": {
"code": "errorCode",
"message": "errorMessage",
"exception": "'PARTNER_API_ERROR'"
}
}
}
}
Transformed Error Response:
{
"code": "INVALID_BEER_ID",
"message": "The specified beer ID does not exist",
"exception": "PARTNER_API_ERROR"
}
Use Case: Get coffee product with full response handling
API Success Response:
{
"success": true,
"data": {
"id": 42,
"title": "Ethiopian Yirgacheffe",
"description": "Light roast with floral notes",
"price": 18.99,
"inStock": true
}
}
API Error Response:
{
"success": false,
"error": {
"code": "PRODUCT_NOT_FOUND",
"message": "Coffee product not found",
"statusCode": 404
}
}
Mapping:
{
"method": "GET",
"path": {
"id": productId
},
"response": {
"validation": {
"successCondition": "success = true and $exists(data.id)",
"failureCondition": "success = false or $exists(error)",
"successTransform": {
"productId": "data.id",
"name": "data.title",
"description": "data.description",
"price": "data.price",
"available": "data.inStock",
"currency": "USD"
},
"errorMapping": {
"code": "error.code",
"message": "error.message",
"exception": "'COFFEE_API_ERROR'"
}
}
}
}
Success Output:
{
"productId": 42,
"name": "Ethiopian Yirgacheffe",
"description": "Light roast with floral notes",
"price": 18.99,
"available": true,
"currency": "USD"
}
Error Output:
{
"code": "PRODUCT_NOT_FOUND",
"message": "Coffee product not found",
"exception": "COFFEE_API_ERROR"
}
API Response:
{
"status": "success",
"wines": [
{
"id": 1,
"name": "Merlot",
"vintage": 2019,
"rating": 4.5
},
{
"id": 2,
"name": "Chardonnay",
"vintage": 2020,
"rating": 4.2
}
]
}
Mapping:
{
"method": "GET",
"response": {
"transform": {
"totalWines": "$count(wines)",
"averageRating": "$sum(wines.rating) / $count(wines)",
"wineList": "wines.{
'wineId': id,
'wineName': name,
'year': vintage,
'score': rating
}"
}
}
}
Transformed Response:
{
"totalWines": 2,
"averageRating": 4.35,
"wineList": [
{
"wineId": 1,
"wineName": "Merlot",
"year": 2019,
"score": 4.5
},
{
"wineId": 2,
"wineName": "Chardonnay",
"year": 2020,
"score": 4.2
}
]
}
API Response:
{
"status": "success",
"beer": {
"id": 5,
"name": "Pale Ale",
"type": "ale",
"abv": 5.5,
"available": true
}
}
Mapping:
{
"method": "GET",
"response": {
"transform": {
"beerId": "beer.id",
"beerName": "beer.name",
"alcoholContent": "beer.abv",
"availability": "beer.available ? 'In Stock' : 'Out of Stock'",
"category": "beer.abv > 7 ? 'Strong' : beer.abv > 5 ? 'Medium' : 'Light'"
}
}
}
Transformed Response:
{
"beerId": 5,
"beerName": "Pale Ale",
"alcoholContent": 5.5,
"availability": "In Stock",
"category": "Medium"
}
Mapping:
{
"method": "POST",
"body": { ... },
"response": {
"transform": {
"requestId": "$uuid()",
"timestamp": "$now()"
},
"validation": {
"successCondition": "status = 'success'",
"successTransform": {
"orderId": "data.orderId",
"status": "'COMPLETED'",
"total": "data.totalAmount"
},
"failureCondition": "status = 'error'",
"errorMapping": {
"code": "error.errorCode",
"message": "error.errorMessage",
"exception": "'ORDER_FAILED'"
}
}
}
}
On Success:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2025-01-15T10:30:00.000Z",
"orderId": "ORD123",
"status": "COMPLETED",
"total": 125.50
}
On Failure:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2025-01-15T10:30:00.000Z",
"code": "PAYMENT_DECLINED",
"message": "Payment method was declined",
"exception": "ORDER_FAILED"
}
When using iteration, response transformation is applied to each individual response:
Mapping:
{
"method": "POST",
"iterateOver": "ORDERS",
"iterationResponseKey": "orderResults",
"body": {
"orderId": "ORDERS[CURRENT_ITERATION].id"
},
"response": {
"validation": {
"successCondition": "status = 'processed'",
"successTransform": {
"orderId": "orderId",
"result": "'SUCCESS'",
"confirmationNumber": "confirmationId"
},
"failureCondition": "status = 'failed'",
"errorMapping": {
"code": "errorCode",
"message": "errorMessage",
"exception": "'ORDER_PROCESSING_ERROR'"
}
}
}
}
Each iteration's response is transformed individually before being collected in the orderResults array.
Do:
$exists() checksfield ? field : "default"Don't:
{
"response": {
"validation": {
"successCondition": "statusCode >= 200 and statusCode < 300",
"failureCondition": "statusCode >= 400"
}
}
}
{
"response": {
"validation": {
"successCondition": "success = true",
"failureCondition": "success = false"
}
}
}
{
"response": {
"validation": {
"successCondition": "$not($exists(error))",
"failureCondition": "$exists(error)"
}
}
}
{
"response": {
"validation": {
"successCondition": "$exists(result) and result.status = 'OK'",
"failureCondition": "$exists(error) or result.status != 'OK'"
}
}
}
The Integration Management Engine provides comprehensive support for handling file attachments in your integrations. This includes generating secure download URLs, retrieving file content, and working with attachments in repeater/array structures.
For complete documentation on attachment functions, see:
Attachment Submission Guide
The attachment guide covers:
Iteration allows you to send multiple API requests, one for each item in an array. This is useful when the partner API requires individual submissions rather than batch processing.
Specify the array field name to iterate over:
{
"method": "POST",
"iterateOver": "EMPLOYEES",
"iterationResponseKey": "employeeIds",
"body": {
"name": "EMPLOYEES[CURRENT_ITERATION].name",
"nid": "EMPLOYEES[CURRENT_ITERATION].nationalId"
}
}
How it works:
EMPLOYEES arrayCURRENT_ITERATION is set (0, 1, 2, ...)employeeIdsSpecify a fixed number of iterations:
{
"method": "POST",
"iterationCount": 5,
"iterationResponseKey": "results",
"body": {
"index": CURRENT_ITERATION,
"data": ITEMS[CURRENT_ITERATION]
}
}
This will make exactly 5 API requests with CURRENT_ITERATION values 0-4.
When using iteration, CURRENT_ITERATION is automatically added to your payload:
{
"method": "POST",
"iterateOver": "BENEFICIAL_OWNERS",
"iterationResponseKey": "ownerIds",
"body": {
"name": "BENEFICIAL_OWNERS[CURRENT_ITERATION].ownerName",
"shares": "BENEFICIAL_OWNERS[CURRENT_ITERATION].sharePercentage",
"idDocument": "getAttachmentContentFromrepeater(BENEFICIAL_OWNERS, idCard)"
}
}
Use Case: Search for a specific beer by name
Endpoint: https://api.sampleapis.com/beers/ale
Input:
{
"searchName": "Sierra Nevada",
"minRating": 4.0
}
Mapping:
{
"method": "GET",
"query": {
"name": searchName
}
}
Result:
https://api.sampleapis.com/beers/ale?name=Sierra%20NevadaSample Response:
[
{
"id": 5,
"name": "Sierra Nevada Pale Ale",
"price": "$15.49",
"rating": {
"average": 4.27,
"reviews": 414
},
"image": "https://www.totalwine.com/media/..."
}
]
Use Case: Add a new coffee product to the catalog
Endpoint: https://api.sampleapis.com/coffee/hot
Input:
{
"productName": "Ethiopian Yirgacheffe",
"productDescription": "Light roast with floral and citrus notes. Grown in the highlands of Ethiopia.",
"ingredients": ["Arabica Coffee Beans", "Water"],
"origin": "Ethiopia",
"roastLevel": "Light",
"price": 18.99
}
Mapping:
{
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"title": productName,
"description": productDescription,
"ingredients": ingredients,
"region": origin,
"roast": roastLevel,
"price": "$" & $string(price)
}
}
Result Body:
{
"title": "Ethiopian Yirgacheffe",
"description": "Light roast with floral and citrus notes. Grown in the highlands of Ethiopia.",
"ingredients": ["Arabica Coffee Beans", "Water"],
"region": "Ethiopia",
"roast": "Light",
"price": "$18.99"
}
Use Case: Retrieve specific wine details by ID with API key authentication
Endpoint: https://api.sampleapis.com/wines/reds/{id}
Input:
{
"wineId": "6",
"userId": "user123"
}
Mapping:
{
"method": "GET",
"auth": {
"type": "API_KEY",
"parameters": {
"apiKey": "${WINE_API_KEY}"
},
"tokenConfig": {
"headerName": "X-API-Key"
}
},
"path": {
"id": wineId
},
"headers": {
"X-User-ID": userId,
"Accept": "application/json"
}
}
Result:
https://api.sampleapis.com/wines/reds/6X-API-Key: your_api_keyX-User-ID: user123Accept: application/jsonSample Response:
{
"id": 6,
"winery": "Sine Qua Non",
"wine": "Ratsel Syrah N.V.",
"rating": {
"average": "4.9",
"reviews": "68 ratings"
},
"location": "United States · California",
"image": "https://images.vivino.com/..."
}
Use Case: Submit wine tasting order with multiple selections
Endpoint: https://api.sampleapis.com/wines/orders
Input:
{
"customerId": "CUST12345",
"customerName": "Jane Smith",
"customerEmail": "jane@example.com",
"WINE_SELECTIONS": [
{
"wineName": "Cabernet Sauvignon",
"wineType": "Red",
"quantity": 2,
"pricePerBottle": 45.00
},
{
"wineName": "Chardonnay",
"wineType": "White",
"quantity": 3,
"pricePerBottle": 38.00
},
{
"wineName": "Merlot",
"wineType": "Red",
"quantity": 1,
"pricePerBottle": 52.00
}
]
}
Mapping:
{
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"customer": {
"id": customerId,
"name": customerName,
"email": customerEmail
},
"items": WINE_SELECTIONS.{
"wine": wineName,
"type": wineType,
"qty": quantity,
"unitPrice": pricePerBottle,
"subtotal": quantity * pricePerBottle
},
"summary": {
"totalItems": $count(WINE_SELECTIONS),
"totalBottles": $sum(WINE_SELECTIONS.quantity),
"totalAmount": $sum(WINE_SELECTIONS.(quantity * pricePerBottle))
},
"orderDate": $now()
}
}
Result Body:
{
"customer": {
"id": "CUST12345",
"name": "Jane Smith",
"email": "jane@example.com"
},
"items": [
{
"wine": "Cabernet Sauvignon",
"type": "Red",
"qty": 2,
"unitPrice": 45.00,
"subtotal": 90.00
},
{
"wine": "Chardonnay",
"type": "White",
"qty": 3,
"unitPrice": 38.00,
"subtotal": 114.00
},
{
"wine": "Merlot",
"type": "Red",
"qty": 1,
"unitPrice": 52.00,
"subtotal": 52.00
}
],
"summary": {
"totalItems": 3,
"totalBottles": 6,
"totalAmount": 256.00
},
"orderDate": "2025-01-15T10:30:00.000Z"
}
Use Case: Rate multiple beers individually (API requires one rating per request)
Endpoint: https://api.sampleapis.com/beers/ale
Input:
{
"userId": "USER789",
"BEER_RATINGS": [
{
"beerId": "5",
"beerName": "Sierra Nevada Pale Ale",
"userRating": 4.5,
"reviewText": "Excellent hoppy flavor"
},
{
"beerId": "12",
"beerName": "Blue Moon Belgian White",
"userRating": 4.0,
"reviewText": "Smooth and refreshing"
},
{
"beerId": "8",
"beerName": "Guinness Draught",
"userRating": 5.0,
"reviewText": "Perfect stout!"
}
]
}
Mapping:
{
"method": "POST",
"iterateOver": "BEER_RATINGS",
"iterationResponseKey": "ratingResults",
"auth": {
"type": "USER_CREDENTIALS",
"baseUrl": "https://api.sampleapis.com/auth",
"parameters": {
"authPath": "/login",
"method": "POST",
"bodyTemplate": {
"email": $."BEER_API_USERNAME",
"password": $."BEER_API_PASSWORD"
}
},
"tokenConfig": {
"storageKey": "beer_api_token",
"headerName": "Authorization",
"tokenPrefix": "Bearer",
"expiryBuffer": 86400,
"extractPath": "data.token"
}
},
"body": {
"userId": userId,
"beerId": "BEER_RATINGS[CURRENT_ITERATION].beerId",
"rating": {
"score": "BEER_RATINGS[CURRENT_ITERATION].userRating",
"review": "BEER_RATINGS[CURRENT_ITERATION].reviewText"
},
"timestamp": $now()
}
}
Processing:
$."BEER_API_USERNAME" and $."BEER_API_PASSWORD")Response:
{
"ratingResults": [
{"beerId": "5", "status": "success", "ratingId": "R001"},
{"beerId": "12", "status": "success", "ratingId": "R002"},
{"beerId": "8", "status": "success", "ratingId": "R003"}
]
}
Key Points:
$."VARIABLE_NAME" syntax in bodyTemplate for authenticationUse Case: Create different coffee recommendations based on preference
Endpoint: https://api.sampleapis.com/coffee/recommendations
Input:
{
"customerName": "Alice Brown",
"preferenceType": "strong",
"budget": 25.00,
"allergies": ["dairy"]
}
Mapping:
{
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"customer": customerName,
"recommendations": preferenceType = "strong"
? {
"roastLevel": "Dark",
"brewMethod": "Espresso",
"suggestedProducts": ["French Roast", "Italian Espresso", "Dark Colombian"]
}
: preferenceType = "mild"
? {
"roastLevel": "Light",
"brewMethod": "Pour Over",
"suggestedProducts": ["Breakfast Blend", "Costa Rican Light", "Ethiopian"]
}
: {
"roastLevel": "Medium",
"brewMethod": "Drip",
"suggestedProducts": ["House Blend", "Colombian Medium", "Breakfast Roast"]
},
"filters": {
"maxPrice": budget,
"excludeIngredients": allergies,
"dairyFree": $exists(allergies) and $contains($string(allergies), "dairy")
}
}
}
Result Body:
{
"customer": "Alice Brown",
"recommendations": {
"roastLevel": "Dark",
"brewMethod": "Espresso",
"suggestedProducts": ["French Roast", "Italian Espresso", "Dark Colombian"]
},
"filters": {
"maxPrice": 25.00,
"excludeIngredients": ["dairy"],
"dairyFree": true
}
}
Use Case: Create beer rating with full error handling and response transformation
Endpoint: https://api.sampleapis.com/beers/ale
Input:
{
"userId": "USER123",
"beerId": "5",
"userRating": 4.5,
"reviewText": "Excellent beer!",
"timestamp": "2025-01-15T10:30:00Z"
}
Mapping:
{
"method": "POST",
"auth": {
"type": "USER_CREDENTIALS",
"baseUrl": "https://api.sampleapis.com/auth",
"parameters": {
"authPath": "/login",
"method": "POST",
"bodyTemplate": {
"email": $."BEER_API_USERNAME",
"password": $."BEER_API_PASSWORD"
}
},
"tokenConfig": {
"storageKey": "beer_api_token",
"headerName": "Authorization",
"tokenPrefix": "Bearer",
"extractPath": "data.token"
}
},
"body": {
"userId": userId,
"beer": {
"id": beerId,
"rating": userRating,
"review": reviewText
},
"submittedAt": timestamp
},
"response": {
"validation": {
"successCondition": "status = 'success' and $exists(data.ratingId)",
"failureCondition": "status = 'error' or $exists(error)",
"successTransform": {
"ratingId": "data.ratingId",
"beerId": "data.beer.id",
"beerName": "data.beer.name",
"userRating": "data.rating",
"averageRating": "data.beer.averageRating",
"totalReviews": "data.beer.totalReviews",
"message": "'Rating submitted successfully'",
"submissionTime": "data.timestamp"
},
"errorMapping": {
"code": "error.code",
"message": "error.message",
"exception": "'RATING_SUBMISSION_ERROR'"
}
}
}
}
Success API Response:
{
"status": "success",
"data": {
"ratingId": "R12345",
"beer": {
"id": "5",
"name": "Sierra Nevada Pale Ale",
"averageRating": 4.3,
"totalReviews": 415
},
"rating": 4.5,
"timestamp": "2025-01-15T10:30:05Z"
}
}
Transformed Success Response:
{
"ratingId": "R12345",
"beerId": "5",
"beerName": "Sierra Nevada Pale Ale",
"userRating": 4.5,
"averageRating": 4.3,
"totalReviews": 415,
"message": "Rating submitted successfully",
"submissionTime": "2025-01-15T10:30:05Z"
}
Error API Response:
{
"status": "error",
"error": {
"code": "BEER_NOT_FOUND",
"message": "The specified beer ID does not exist in our database",
"details": {
"beerId": "5",
"timestamp": "2025-01-15T10:30:05Z"
}
}
}
Transformed Error Response:
{
"code": "BEER_NOT_FOUND",
"message": "The specified beer ID does not exist in our database",
"exception": "RATING_SUBMISSION_ERROR"
}
Key Features:
$."VARIABLE" for authentication credentialsDo:
Don't:
$exists() to check)Do:
fieldName ? fieldName : "default"Example:
{
"email": $exists(emailAddress) ? emailAddress : "not_provided@irembo.gov.rw",
"phone": $exists(phoneNumber) ? phoneNumber : null
}
Do:
generateAttachmentURL() instead of getAttachmentContent() when possibleDon't:
Do:
Don't:
Do:
Example Documentation:
Endpoint: NIDA_VERIFY_ID
Purpose: Verify national ID with NIDA system
Auth: USER_CREDENTIALS via environment variables
Input: nationalId (required)
Output: verification status and personal details
Last Updated: 2025-01-15
Symptoms: Mapping fails with syntax error
Solutions:
Example Error:
Missing closing brace in object definition
Symptoms: Error indicates a variable is not defined
Solutions:
$."VARIABLE_NAME" in auth parameters, use ${VARIABLE_NAME} elsewhereExample:
Wrong: ${WINE_API_USERNAM}
Correct: $."WINE_API_USERNAME" (in auth.parameters)
Correct: ${WINE_API_USERNAME} (in headers/body)
Symptoms: Raw variable strings appear in request (e.g., ${API_KEY} or $."API_KEY" in output)
Cause: Using wrong syntax in wrong place
Solutions:
In auth.parameters.bodyTemplate - Use $."VARIABLE":
{
"auth": {
"parameters": {
"bodyTemplate": {
"email": $."API_USERNAME" // ✓ Correct
}
}
}
}
In headers, body, query - Use ${VARIABLE}:
{
"headers": {
"X-API-Key": "${API_KEY}" // ✓ Correct
},
"body": {
"apiSecret": "${API_SECRET}" // ✓ Correct
}
}
Quick Reference:
| Location | Syntax | Example |
|---|---|---|
auth.parameters.bodyTemplate |
$."VARIABLE" |
$."API_USERNAME" |
auth.parameters (other) |
$."VARIABLE" |
$."API_KEY" |
headers |
${VARIABLE} |
${API_KEY} |
body |
${VARIABLE} |
${SECRET} |
query |
${VARIABLE} |
${TOKEN} |
Symptoms: Cannot parse input or output JSON
Solutions:
Symptoms: Attachment URLs or content not generated
Solutions:
See the Attachment Submission Guide for detailed troubleshooting of attachment-related issues, including:
Symptoms: Unauthorized or authentication errors
Solutions:
baseUrl and authPath point to correct endpointsextractPath matches the auth response structure$."VARIABLE_NAME" syntax in auth.parameters.bodyTemplate, not ${VARIABLE_NAME}Example of correct vs incorrect syntax:
Wrong:
{
"auth": {
"parameters": {
"bodyTemplate": {
"email": "${API_USERNAME}", // ❌ Won't work
"password": "${API_PASSWORD}" // ❌ Won't work
}
}
}
}
Correct:
{
"auth": {
"parameters": {
"bodyTemplate": {
"email": $."API_USERNAME", // ✓ Works
"password": $."API_PASSWORD" // ✓ Works
}
}
}
}
Example extractPath debugging:
// Auth Response:
{
"data": {
"access_token": "eyJhbGc...",
"expires_in": 3600
}
}
// Correct extractPath:
"extractPath": "data.access_token"
// Wrong:
"extractPath": "access_token"
Symptoms: Only one request sent instead of multiple
Solutions:
iterateOver field name matches your array field exactlyCURRENT_ITERATION is used correctly in expressionsExample:
// Wrong - hardcoded index
"name": "EMPLOYEES[0].name"
// Correct - uses current iteration
"name": "EMPLOYEES[CURRENT_ITERATION].name"
Symptoms: Output doesn't match expectations
Solutions:
? :) evaluates correctlySymptoms: Original API response returned instead of transformed response
Cause:
Solutions:
$exists() to check for required fieldsExample:
// Wrong - string instead of boolean
"successCondition": "status" // ❌
// Correct - boolean expression
"successCondition": "status = 'success'" // ✓
Symptoms: Errors not mapped to expected format
Solutions:
failureCondition correctly identifies errorsExample:
{
"response": {
"validation": {
"failureCondition": "$exists(error) or status = 'failed'", // ✓ Multiple conditions
"errorMapping": {
"code": "error.errorCode", // Must match actual response
"message": "error.errorMessage", // Must match actual response
"exception": "'PARTNER_API_ERROR'"
}
}
}
}
When reporting issues, provide:
Contact the integration team with this information for faster resolution.
Authentication Types:
TOKEN - Static API tokenUSER_CREDENTIALS - Username/Password flowCLIENT_CREDENTIALS - OAuth 2.0BASIC - HTTP Basic AuthAPI_KEY - API key in headerAttachment Functions:
generateAttachmentURL(field) - Generate download URLgetAttachmentContent(field) - Get base64 contentgenerateAttachmentURLFromrepeater(repeater, field) - URL from arraygetAttachmentContentFromrepeater(repeater, field) - Content from arrayCommon JSONata Functions:
$exists(field) - Check if field exists$sum(array) - Sum array values$count(array) - Count array elements$now() - Current timestamp$uppercase(string) - Convert to uppercase$lowercase(string) - Convert to lowercaseThe Integration Management Engine provides flexible, powerful integration capabilities through:
$."VAR" and ${VAR})This design enables rapid integration development while maintaining security, performance, and ease of use.