Mongrel.io User Documentation
Overview
Mongrel.io lets you create API endpoints that read from and write to multiple external APIs, transform data with JavaScript at every stage, and deliver a unified response — all without writing backend code. You can also forward data to downstream destinations such as webhooks, third-party APIs, or analytics services.
Each route you create becomes a live API endpoint with its own URL. A route is made up of five configurable sections:
- Name — Identify your route
- Authentication — Control who can access it
- Request — Define the incoming HTTP path and method
- Sources — Read from or write to external APIs, with optional transforms to shape request bodies
- Response — Transform the combined source data and configure the output format
You can also add Destinations to forward data to other services, each with their own optional transform to tailor the payload per recipient.
Getting Started
This walkthrough creates a simple route that reads user data from a public API, transforms it, and returns a clean JSON response. For examples of writing to external APIs, see Source Transform Function and Common Patterns.
Step 1: Create an API
After signing in at app.mongrel.io, create a new API from the dashboard. Each API has its own base URL (e.g. https://my-app.api.mongrel.io).
Step 2: Create a Route
Click + Create Route in the sidebar. You'll see the route editor with sections for Name, Authentication, Request, Sources, and Response.
Step 3: Configure the Route
Name: Enter a descriptive name (e.g. Getting Started). This appears in logs and the sidebar.
Request: Set the HTTP method to GET and enter a path like getting-started/hello. Your full endpoint URL will be shown (e.g. https://my-app.api.mongrel.io/getting-started/hello).
Source: Click + Add Source and configure it:
- Name:
usersApi(this is how you reference it in transforms) - Method:
GET - URL:
https://jsonplaceholder.typicode.com/users/1 - Content-type:
JSON
Response Transform: Click Edit on the Response Body and write a transform function:
function transform(data) {
var user = data.sources.usersApi;
return {
name: user.name,
email: user.email,
city: user.address.city,
company: user.company.name
};
}
This function accesses the source data via data.sources.usersApi (matching the source name) and returns only the fields you want.
Step 4: Publish
Click Publish to make your route live. You can test it immediately:
curl https://my-app.api.mongrel.io/getting-started/hello
Response:
{
"name": "Leanne Graham",
"email": "Sincere@april.biz",
"city": "Gwenborough",
"company": "Romaguera-Crona"
}
Combining Multiple Sources
A key feature of Mongrel.io is interacting with multiple APIs in a single request. Here's an example that reads user details and their posts, then merges them into one response:
Source 1 — userDetails:
- URL: https://jsonplaceholder.typicode.com/users/1
- Content-type: JSON
Source 2 — userPosts:
- URL: https://jsonplaceholder.typicode.com/posts?userId=1
- Content-type: JSON
Response Transform:
function transform(data) {
var user = data.sources.userDetails;
var posts = data.sources.userPosts;
var result = new Object();
result.name = user.name;
result.email = user.email;
result.postCount = posts.length;
result.latestPost = posts[0].title;
return result;
}
This combines data from two independent API calls into a single response — no backend server required.
Name
- Required: Yes
- Description: The name of the route. Used to identify the route in logs, the sidebar, and publish events
- Example:
My Route
Route Authentication
Control how clients authenticate when accessing your API endpoint. Choose from three authentication methods.
None
No authentication required. Anyone with your endpoint URL can access it.
API Key
Require clients to include a valid API key with each request. The token should be passed in an X-Mongrel-Api-Key header.
JWT (JSON Web Token)
Validate requests using signed JSON Web Tokens.
JWKS URL
- Required: Yes
- Description: The URL where your identity provider publishes its JSON Web Key Set. Used to verify token signatures.
- Example:
https://auth.example.com/.well-known/jwks.json
Request
The Request section defines how external clients will call your API endpoint.
Path
- Required: Yes
- Description: The URL path where your endpoint will be accessible
- Example:
api/usersordata/products/{id} - Supports Parameters: Use curly braces for path parameters (e.g.,
{id},{userId})
Method
- Required: Yes
- Options:
GET,PUT,POST,PATCH,DELETE - Description: The HTTP method your endpoint will accept
Content Type
- Required: No
- Options:
application/jsonapplication/xmltext/csv- Empty (no body expected)
- Description: The format of the incoming request body
Parse Options
See Parsing Options
CORS Options
Configure Cross-Origin Resource Sharing for browser-based clients.
Allowed Origins
- Format: Comma separated list of URLs
- Description: List of origins permitted to access this endpoint
- Example:
https://example.com,https://dev.example.com - Validation: Must be valid URLs
Allowed Headers
- Format: Comma separated list of header names
- Description: HTTP headers that can be used in requests
- Example:
Content-Type,Authorization - Validation: Must match pattern
[\w-]+
Sources
Sources are external APIs that your route interacts with before transformation. With GET sources, your route reads data from the API. With POST, PUT, or PATCH sources, your route writes data to the API using a source transform to shape the request body. You can add multiple sources — both reading and writing — and access all of their responses in the response transform.
Name
- Required: Yes
- Description: Unique identifier for this source within your transformation function
- Validation: Must be a valid JavaScript identifier
- Usage: Access source data in transforms via
data.sources.{name} - Example:
userData,productInfo
Method
- Required: Yes
- Options:
GET,POST,PUT,PATCH - Default:
GET - Description: The HTTP method used when calling this source API. Use
GETto read data, orPOST,PUT,PATCHto write data
Note: When using
POST,PUT, orPATCH, you must provide a source transform function that shapes the request body to send.GETsources cannot have a transform function.
URL
- Required: Yes
- Description: The full URL of the external API to call
- Example:
https://api.example.com/users - Supports Variables: Yes — see Using Variables in URLs
Content Type
- Required: Yes
- Options:
- JSON (
application/json) - XML (
application/xml) - CSV (
text/csv)
- JSON (
- Description: The format of data exchanged with the source API. For
GETrequests, this is the response format. ForPOST,PUT, andPATCH, this applies to both the request body sent and the response received
Authentication
Cache Options
Enable caching to reduce the number of calls to a source API.
- Enabled: Boolean — turn caching on or off
- TTL (Time to Live): Number — how long (in seconds) to cache the source response before making a new call
When caching is enabled, repeated calls to the same source will return the cached response until the TTL expires.
Source Transform Function
For POST, PUT, and PATCH sources, you must provide a transform function that returns the request body to send to the source API. This is how your route writes data to external APIs. The function receives the same data object as the response transform, giving you access to the incoming request data and responses from previously executed sources.
Example: Create a record in an external API
function transform(data) {
return {
name: data.request.body.name,
email: data.request.body.email,
createdBy: "mongrel-route"
};
}
Example: Update an external API using data from another source
function transform(data) {
var user = data.sources.userLookup;
return {
userId: user.id,
accountId: user.accountId,
action: data.request.body.action
};
}
The response from a write source is available in data.sources.{name} just like a read source, so you can use the API's response (e.g. a created record ID) in your response transform or in subsequent sources.
Test Source
Each source has a Test Source button that lets you make a test call to the configured API and see the response. This is useful for:
- Verifying the URL and authentication are correct
- Checking the response format and structure
- For write sources (
POST,PUT,PATCH), verifying the request body is shaped correctly - Understanding the data before writing transforms
Parse Options
See Parsing Options
Transform and Response
The Response section defines how your route's output will be returned to the caller. The core of this section is the transform function, where you combine and reshape data from all source responses — whether those sources were reading data or writing it — into your desired output.
Transform Function
Function Requirements
- Parameters: Must accept exactly one parameter (typically named
data) - Return: Must return a value
- Language: JavaScript (ECMAScript 2020)
- Validation: Code is validated for correct syntax and structure
- Supports: Function declarations, function expressions, and arrow functions
Input Data Structure
Your function receives a data object with the following structure:
{
request: {
body: {}, // Parsed request body (if any)
path: {}, // Path parameters as key-value pairs
query: {}, // Query parameters (values are arrays)
headers: {} // Request headers (values are arrays)
},
sources: {
sourceName: {}, // Response data from each source by name
anotherSource: {}
},
item: {} // Present when split is enabled
}
Transform Debugger
The transform editor includes a Test Function button that opens the transform debugger. This tool lets you:
- Provide sample input data
- Execute the transform function
- See the output or any errors
Use it to iterate on your transform logic before publishing.
Accessing Data from Different Formats
The way you access data in your transformation function depends on the content type of your sources.
JSON Source Data
JSON sources are parsed into JavaScript objects, allowing direct property access:
function(data) {
const dev = data.sources.devApi.developer;
return {
name: dev.name,
email: dev.email
};
}
XML Source Data
XML sources are converted to JavaScript objects. Element attributes use the configured prefix (default @_), and text content uses the text node name:
function(data) {
const devs = data.sources.standupApi.standup_notes.developer;
return devs.map(dev => ({
id: dev["@_id"],
name: dev.name,
blocked: dev.blockers["@_status"] === "ongoing"
}));
}
CSV Source Data
CSV sources are parsed as arrays of objects (when objectMode: true) or arrays of arrays:
function(data) {
const devs = data.sources.devCsv;
return devs.map(dev => ({
developerId: parseInt(dev.dev_id),
name: dev.name,
language: dev.language
}));
}
Function Examples
Simple Pass-Through
function transform(data) {
return data.sources.myApi;
}
Combining Multiple Sources
function transform(data) {
return {
user: data.sources.userApi,
orders: data.sources.orderApi,
timestamp: Date.now()
};
}
Filtering with Query Parameters
function transform(data) {
const users = data.sources.userList;
const filter = data.request.query.status?.[0] || 'active';
return users
.filter(user => user.status === filter)
.map(user => ({
id: user.id,
fullName: `${user.firstName} ${user.lastName}`,
email: user.email
}));
}
Response Code
- Required: Yes
- Options:
200,201,202 - Description: HTTP status code for successful responses
Response Content Type
- Required: Yes
- Options:
application/jsonapplication/xmltext/csv
- Description: Format for the response body
Response Cache Options
Enable caching on the response to reduce processing for repeated identical requests.
- Enabled: Boolean — turn caching on or off
- TTL (Time to Live): Number — how long (in seconds) to cache the response
When enabled, the full response (after all source calls and transformation) is cached. Subsequent identical requests return the cached result until the TTL expires.
Write Options
See Writing Options
Destinations
Define zero or more destinations to forward your data to after the response is generated.
Name
- Required: Yes
- Description: Identifier for this destination
- Validation: Must be a valid JavaScript identifier
- Example:
webhook,analyticsApi
URL
- Required: Yes
- Description: Target endpoint URL
- Example:
https://webhook.example.com/data - Supports Variables: Yes — see Using Variables in URLs
Content Type
- Required: Yes
- Options:
application/json,application/xml,text/csv - Description: Format for data sent to this destination
Method
- Required: Yes
- Options:
GET,PUT,PATCH,POST,DELETE - Description: HTTP method to use when sending to destination
Split
- Type: Boolean
- Default:
false - Description: When
true, if the response data is an array, each item is sent as a separate HTTP request to this destination
Authentication
Write Options
See Writing Options
Destination Transform Function
- Required: No
- Available for:
PUT,PATCH,POST,DELETEmethods (notGET) - Description: A JavaScript function that transforms the response data before it is sent to this destination. This enables the Backend for Frontend (BFF) pattern where each destination can receive a differently shaped payload.
When no transform function is provided, the destination receives the response data as-is.
Input Data Structure
The destination transform function receives a data object with the following structure:
{
request: {
body: {}, // Parsed request body (if any)
path: {}, // Path parameters
query: {}, // Query parameters
headers: {} // Request headers
},
sources: {
sourceName: {}, // Response data from each source by name
},
response: {} // The response transform result
}
When split mode is enabled, data.response contains the individual array item being processed, not the full array.
Example: Filter Fields for a Webhook
function transform(data) {
return {
email: data.response.email,
event: "user_updated",
timestamp: Date.now()
};
}
Example: Reshape for a Third-Party API
function transform(data) {
const orders = Array.isArray(data.response) ? data.response : [data.response];
return {
total: orders.length,
revenue: orders.reduce((sum, o) => sum + o.amount, 0),
currency: orders[0]?.currency || "USD"
};
}
Authentication Options
Configure how to authenticate with an external source or destination.
Type: BASIC
HTTP Basic Authentication - username: Username for authentication - password: Password for authentication
Type: HEADER_KEY
API key in request header
- keyName: Name of the header (e.g., X-API-Key)
- apiKey: The API key value
Type: QUERY_KEY
API key in query parameter
- keyName: Name of the query parameter (e.g., api_key)
- apiKey: The API key value
Type: BEARER_TOKEN
Bearer token authentication - token: The bearer token value
Type: OIDC
OpenID Connect authentication - tokenUrl: OAuth token endpoint URL - clientId: OAuth client ID - clientSecret: OAuth client secret - scope: Requested OAuth scopes - token (optional): Cached token (managed automatically)
Parsing Options
Parse options vary based on the selected content type:
JSON Parse Options
Currently no specific parse options are required for JSON.
XML Parse Options
Attribute Handling
-
ignoreAttributes: When enabled, all element attributes are excluded from parsing. Set to
trueto treat everything as tags only, orfalseto include attributes in the output. -
allowBooleanAttributes: Enables parsing of attributes that have no value assignment (e.g.,
<input checked>). When set totrue, these attributes appear in the output with a value oftrue. Must be used withignoreAttributes: false. -
attributeNamePrefix: String prepended to all attribute names to distinguish them from child elements in the output object. Common value is
@_. Only applies whenignoreAttributesisfalse. -
attributesGroupName: When specified, collects all attributes of an element under a single property with this name. Helps separate attributes from child elements. Requires
ignoreAttributes: false.
Text Content
-
textNodeName: Specifies the property name used for the text content of elements. Useful when an element has both text and attributes or child elements. Default varies based on other settings.
-
alwaysCreateTextNode: Forces creation of a dedicated text node property even for simple text-only elements. When
false, simple text is assigned directly to the tag property. -
trimValues: Removes leading and trailing whitespace from all text values and attribute values during parsing.
Special Content Types
-
cdataPropName: Property name used to identify CDATA sections in the output. If not specified, CDATA content is merged with regular text content.
-
commentPropName: Property name for preserving XML comments in the parsed output. Comments are typically ignored unless this is set. Works best with
preserveOrder: true.
Structure and Order
-
preserveOrder: Maintains the exact order of elements as they appear in the XML document. When enabled, the output structure changes to preserve sequence, which is especially important for mixed content.
-
arrayPaths: Comma-separated list of element paths that should always be parsed as arrays, even when only one element exists. Helpful for consistent data structures.
Namespaces and Entities
-
removeNsPrefix: Strips namespace prefixes from element and attribute names (e.g., converts
ns:tagNametotagName). -
processEntities: Controls whether XML entities (like
<,>,&) and DOCTYPE entities are decoded during parsing. Enabled by default. Disable for better performance if your XML doesn't contain entities. -
htmlEntities: Enables recognition and parsing of HTML-specific entities beyond standard XML entities.
Processing Control
-
stopNodes: Comma-separated list of element paths where parsing should halt, leaving the content as raw text. Useful for elements like
<script>or<pre>where you want to preserve content exactly. Can use wildcards (e.g.,*.script). -
ignorePiTags: When enabled, skips processing instruction tags (e.g.,
<?xml-stylesheet ?>). -
ignoreDeclaration: Excludes the XML declaration (e.g.,
<?xml version="1.0"?>) from the parsed output. -
unpairedTags: Comma-separated list of tag names that are self-closing and don't require a closing tag (e.g., HTML tags like
br,img,hr).
CSV Parse Options
Data Format
-
objectMode: Controls the output format of parsed rows. When
true(default), each row is returned as an object with column names as keys. Whenfalse, rows are returned as arrays of values. -
delimiter: The character used to separate columns in your CSV file. Defaults to comma (
,). Change this if your file uses alternative separators like semicolon (;) or tab (\t). Must be a single character. -
headers: Determines how column headers are handled. Set to
trueto use the first row as headers. Provide a string array to manually define header names. Set tofalse(default) if your CSV has no headers. Headers must be unique or parsing will fail. -
renameHeaders: When enabled, replaces the first row of the CSV with custom headers specified in the
headersoption. Only applies whenheadersis provided as an array. Use this when you want to discard the original header row.
Quote and Escape Handling
-
quote: The character used to wrap fields containing special characters like delimiters or line breaks. Defaults to double quote (
"). Set to empty string to disable quote handling entirely. -
escape: Character used to include a quote character within a quoted field. Defaults to double quote (
").
Whitespace Management
-
trim: Removes whitespace from both the beginning and end of all column values.
-
ltrim: Strips whitespace only from the left (beginning) of column values.
-
rtrim: Removes whitespace only from the right (end) of column values.
Row Filtering
-
ignoreEmpty: Skips rows that are completely empty or contain only whitespace and delimiters.
-
comment: Single character that marks a line as a comment (e.g.,
#). Lines starting with this character are ignored during parsing. -
maxRows: Limits parsing to a specific number of rows. Set to
0or leave unset for no limit. -
skipRows: Number of data rows to skip after headers are processed.
-
skipLines: Number of raw lines to skip from the beginning of the file before parsing starts.
Column Handling
-
discardUnmappedColumns: When enabled, any columns beyond the number of defined headers are silently dropped.
-
strictColumnHandling: Treats rows with column count mismatches as invalid rather than throwing errors.
Encoding
- encoding: Character encoding of the CSV file. Defaults to
utf8. Change toutf16le,ascii, oriso-8859-1if your file uses a different encoding.
Writing Options
Write options vary based on the selected content type:
JSON Write Options
- includeFields: Comma-separated list of fields to include in output
- indent: Number of spaces for JSON formatting (omit for compact JSON)
XML Write Options
Structure and Formatting
-
format: Enables pretty-printing of the XML output with proper indentation and line breaks. When
false, produces compact single-line XML. -
indentBy: Defines the string used for each indentation level when formatting is enabled. Common values include two spaces or a tab character. Only applies when
formatistrue. -
arrayNodeName: Specifies the tag name to use when building XML from an array at the root level.
-
preserveOrder: Maintains the exact sequence of elements as they exist in the JavaScript object. Should match the parser setting if round-tripping data.
Attribute Control
-
ignoreAttributes: When
true, skips all attributes during XML generation. Can also accept an array of attribute names to selectively exclude. -
attributeNamePrefix: String that identifies attribute properties in the JavaScript object. Must match the parser setting for consistent round-tripping.
-
attributesGroupName: Property name that contains all attributes for an element grouped together.
-
suppressBooleanAttributes: When enabled, attributes with boolean
truevalues are written without values (e.g.,<input checked>).
Text Content
- textNodeName: Identifies which property contains the text value of an element. Typically
"#text".
Special Content Handling
-
cdataPropName: Property name that marks content to be wrapped in CDATA sections.
-
commentPropName: Property name identifying XML comments in the data structure.
Entity Processing
- processEntities: Controls conversion of special characters to XML entities during output. When
true(default), characters like<,>, and&are encoded.
Empty and Self-Closing Tags
-
suppressEmptyNode: When enabled, elements with no content are rendered as self-closing tags.
-
unpairedTags: Comma-separated list of tag names that should be rendered as self-closing tags.
-
suppressUnpairedNode: Controls whether unpaired tags include a closing slash.
Advanced Options
-
oneListGroup: When enabled, wraps array items under a parent container tag.
-
stopNodes: Comma-separated list of element paths where processing should stop, preserving the content as raw text.
CSV Write Options
Field and Row Separators
-
delimiter: Character used to separate columns in the output. Defaults to comma (
,). -
rowDelimiter: Character sequence used to separate rows. Defaults to newline (
\n). -
includeEndRowDelimiter: When enabled, adds a row delimiter after the final row of data.
Quote and Escape Control
-
quote: Character used to wrap field values containing special characters. Defaults to double quote (
"). -
escape: Character used to escape quote characters within quoted fields.
-
quoteColumns: Controls which data columns get quoted. Set to
trueto quote all columns, or use selective options. -
quoteHeaders: Determines which header values are quoted.
Header Configuration
-
headers: Controls header row generation. Set to
trueto auto-detect headers from data. -
writeHeaders: When
false, suppresses the header row entirely. -
alwaysWriteHeaders: Forces header row output even when no data rows are written.
-
forceHeaders: Comma-separated string of header names to force in the output.
Column-Level Quoting
-
quotedColumns: Comma-separated string listing specific column names that should always be quoted.
-
quotedHeaders: Comma-separated string of header names that should be quoted.
Special Options
- writeBOM: When enabled, writes a UTF-8 Byte Order Mark as the first character of the output.
Tools
Mongrel.io provides several tools to help you build, test, and monitor your routes.
Source Tester
Each source configuration includes a Test Source button. Click it to make a live request to the source API and see the response. This lets you verify the URL, authentication, request body (for write sources), and response format before publishing.
Transform Debugger
The transform editor includes a Test Function button that opens the debugger. You can provide sample input data, execute the function, and see the result or errors. Use this to iterate on your transform logic.
Request Logs
The Request Logs view (accessible from the sidebar) shows recent requests to your published routes, including:
- Request timestamp
- HTTP method and path
- Response status code
- Execution time
- Any errors that occurred
Use request logs to monitor your routes and debug issues.
Publish Events
The Publish Events view (accessible from the sidebar) shows a history of publish and unpublish actions for your routes, including:
- When the route was published
- The version that was published
- Whether the publish succeeded or failed
Common Patterns
Using Variables in URLs
Both Source URLs and Destination URLs support template variables, allowing you to dynamically construct URLs based on incoming request data and data from other sources.
Template Syntax
Variables are inserted using JavaScript template literal syntax: ${expression}
Available Data in URLs
You can access the same data object available in transformation functions:
{
request: {
body: {}, // Parsed request body
path: {}, // Path parameters as key-value pairs
query: {}, // Query parameters (values are arrays)
headers: {} // Request headers (values are arrays)
},
sources: {
sourceName: {} // Response data from previously executed sources
}
}
Note: Sources are automatically executed in the correct order based on their dependencies. If one source references another in its URL or transform, the system ensures the referenced source is executed first.
Examples
Using Path Parameters
Request path: /api/users/{userId}/orders/{orderId}
Source URL:
https://api.example.com/users/${data.request.path.userId}
Using Query Parameters
Request: /api/search?status=active&limit=10
Source URL:
https://api.example.com/items?status=${data.request.query.status[0]}&max=${data.request.query.limit[0]}
Remember that query parameter values are arrays, so use [0] to get the first value.
Using Request Headers
Source URL:
https://api.example.com/data?tenant=${data.request.headers['x-tenant-id'][0]}
Using Request Body Fields
Source URL:
https://api.example.com/customers/${data.request.body.customerId}/orders?type=${data.request.body.orderType}
Using Data from Other Sources
You can reference data from other sources to create API call chains:
- Source 1 — Name:
userApi, URL:https://api.example.com/users/${data.request.path.userId} - Source 2 — Name:
ordersApi, URL:https://api.example.com/accounts/${data.sources.userApi.accountId}/orders
The system detects this dependency and ensures userApi executes before ordersApi.
Complex Expressions
https://api.example.com/items?limit=${data.request.query.limit ? data.request.query.limit[0] : '10'}
Best Practices
- URL Encode Values: If your variables might contain special characters, consider handling encoding in your transformation function
- Validate Required Fields: Ensure path parameters and required query parameters are present before they're used in URLs
- Use Fallbacks: Provide default values for optional parameters:
${data.request.query.page?.[0] || '1'} - Source Dependencies: The system automatically resolves source dependencies based on URL references, so you can define sources in any order
Using Path Parameters
// Request path: /users/{userId}/orders/{orderId}
function(data) {
const userId = data.request.path.userId;
const orderId = data.request.path.orderId;
return {
user: userId,
order: orderId,
details: data.sources.orderApi
};
}
Accessing Query Parameters
// Query parameters come as arrays
function(data) {
const limit = parseInt(data.request.query.limit?.[0] || '10');
const page = parseInt(data.request.query.page?.[0] || '1');
return data.sources.items.slice((page - 1) * limit, page * limit);
}
Working with Split Mode
// Transformation returns array
function(data) {
return data.sources.users.map(user => ({
id: user.id,
email: user.email
}));
}
// With split=true on destination, each user object
// is sent as a separate HTTP request
Writing to External APIs
Sources can write data to external APIs using POST, PUT, or PATCH methods. The source transform shapes the request body, and the API's response is available alongside read sources in your response transform.
Example: Create a record and return the result
A route with request method POST and two sources:
- Source 1 —
lookupUser(GET):https://api.example.com/users/${data.request.body.userId} - Source 2 —
createOrder(POST):https://api.example.com/orders
Source transform for createOrder:
function transform(data) {
var user = data.sources.lookupUser;
return {
customerId: user.customerId,
items: data.request.body.items,
shippingAddress: user.defaultAddress
};
}
Response transform:
function transform(data) {
return {
orderId: data.sources.createOrder.id,
status: data.sources.createOrder.status,
customer: data.sources.lookupUser.name
};
}
This pattern reads data from one API, uses it to write to another, and returns a combined response.
Error Handling
Errors in transformation functions or source API calls will result in error responses. Ensure your transformation handles missing or unexpected data gracefully:
function(data) {
const users = data.sources.userApi?.users || [];
return users.map(user => ({
id: user.id,
name: user.name || 'Unknown',
email: user.email || 'no-email@example.com'
}));
}
Troubleshooting
Route won't publish
If clicking Publish does nothing, check for validation errors:
- Invalid JavaScript syntax: Open the transform editor and check for syntax errors. The editor validates your code and shows errors at the bottom.
- Missing required fields: Ensure all sources have a name, URL, and content type. Ensure the request path is set.
- Source transform required: If a source uses
POST,PUT, orPATCH, it must have a transform function.
Source returns unexpected data
- Use the Test Source button to see the raw response from the source API
- Check the content type matches the actual response format (e.g., don't set JSON for an XML response)
- Verify the URL is correct and the API is accessible
- For write sources (
POST,PUT,PATCH), check that the source transform is producing the correct request body
Transform function errors
- Use the Test Function button in the transform editor to debug
- Check you're accessing source data with the correct name:
data.sources.yourSourceName - Ensure your function has a
returnstatement - Remember that query parameters and headers are arrays — use
[0]to access the first value
Cached data is stale
If your route returns stale data, check cache settings:
- Source cache: Disable or reduce TTL on individual source cache options
- Response cache: Disable or reduce TTL on the response cache options
- Unpublish and republish the route to clear caches