Sources
Sources expose producer scripts via a read-only HTTP endpoint. A producer script queries an external register or service and returns a list of structured results. It never modifies any object.
Endpoint
GET /sources/{tenantId}/{sourceName}
Query parameters are passed directly as script parameters.
Example:
GET /sources/3fa85f64-5717-4562-b3fc-2c963f66afa6/CompanySearch?countryCode=nl&query=mosterd
Response
{
"items": [
{
"registrationNumber": "12345678",
"name": "Mosterd BV",
"active": true,
"city": "Amsterdam"
}
],
"notification": null
}
| Field | Type | Description |
|---|---|---|
items | object[] | The list of results returned by the source. Fields depend on the source. |
notification | object | null | An optional message from the script (see below). |
The notification field is only present when the script explicitly set one:
{
"items": [],
"notification": {
"message": "No results found for this query.",
"level": "WARNING"
}
}
Notification levels: INFO, WARNING, ERROR.
Defining a producer script
Add a producerGateway script to a class definition. The class acts as an organisational container — the script itself is GENERAL scope and not tied to any specific object.
{
"name": "CompanySearch",
"type": "producerGateway",
"scope": "GENERAL",
"gateway": "CompanySearch",
"parameters": [
{ "name": "countryCode", "dataType": "TEXT" },
{ "name": "query", "dataType": "TEXT" }
]
}
The script name becomes the {sourceName} in the URL. Parameter names become query string keys.
Available sources
CompanySearch
Searches a national business register by company name. Returns companies matching the search query, including inactive registrations.
Parameters:
| Name | Type | Description |
|---|---|---|
countryCode | TEXT | ISO 3166-1 alpha-2 country code (e.g. nl, gb). |
query | TEXT | Company name or partial name to search for. |
Supported countries:
| Code | Register |
|---|---|
nl | Kamer van Koophandel (KvK) |
gb | Companies House |
Result fields:
| Field | Type | Description |
|---|---|---|
registrationNumber | string | Official registration number in the national register. |
name | string | Registered company name. |
active | boolean | Whether the registration is currently active. |
legalForm | string | Legal form code (e.g. BV, NV). |
city | string | City of the registered address. |
postalCode | string | Postal code of the registered address. |
country | string | Country name. |
registrationDate | string (date) | Date the company was registered. |
endDate | string (date) | Date the registration ended, if inactive. |
Example response:
{
"items": [
{
"registrationNumber": "12345678",
"name": "Mosterd BV",
"active": true,
"legalForm": "BV",
"city": "Amsterdam",
"postalCode": "1012AB",
"country": "Nederland",
"registrationDate": "2010-03-15"
}
],
"notification": null
}
JavaScript producer scripts
A JavaScript script can act as a producer by setting "producer": true. This lets you write custom query and transformation logic using the full script API, and expose the result via the same Sources endpoint.
Definition
{
"name": "ActiveProducts",
"type": "javascript",
"producer": true,
"scope": "GENERAL",
"javascriptFile": "scripts/activeProducts",
"parameters": [
{ "name": "category", "dataType": "TEXT" }
]
}
| Property | Type | Description |
|---|---|---|
producer | boolean | Set to true to mark this JavaScript script as a producer. |
scope | GENERAL | Producer scripts are always GENERAL scope. |
javascriptFile | string | Path to the .js file (without extension). |
javascript | string | Inline JavaScript source (use javascriptFile for anything non-trivial). |
Function signature
The entry point is produce instead of execute. There is no dataObject argument — producers always run without an object context.
function produce(api, params) {
// params — resolved script parameters as a key-value map
// return — an array of plain objects (the items in the response)
}
| Argument | Description |
|---|---|
api | The script API — same methods as for actor scripts. api.notify() sets the response notification. |
params | Resolved script parameters as a key-value map. |
The return value is either an array of plain objects or a single plain object — both are valid. A single object is automatically wrapped in a one-element list. Fields may use any names — the caller receives them as-is.
Example: query platform data
A producer that lists active products in a given category, filtered by a parameter:
function produce(api, params) {
var category = params.category;
var filters = { active: true };
if (category) {
filters.category = category;
}
var products = api.query('products', filters, 'name');
return products.map(function(p) {
return {
reference: p._reference,
name: p.name,
price: p.price,
category: p.category
};
});
}
Call: GET /sources/{tenantId}/ActiveProducts?category=electronics
Example: combine external and platform data
A producer that enriches platform records with data from a related object:
function produce(api, params) {
var contracts = api.query('contracts', { status: 'ACTIVE' }, 'startDate');
return contracts.map(function(c) {
var client = c.client ? api.get(c.client) : null;
return {
reference: c._reference,
clientName: client ? client.name : null,
startDate: c.startDate,
endDate: c.endDate,
value: c.totalValue
};
});
}
Notifications from producers
api.notify() works the same way as in actor scripts — the last call wins. The message is returned in the notification field of the response.
function produce(api, params) {
var results = api.query('invoices', { overdue: true });
if (results.length === 0) {
api.notify('No overdue invoices found.', 'INFO');
}
return results;
}
Use a producerGateway script when the data comes from an external service with a dedicated gateway implementation (e.g. a national business register). Use a JavaScript producer when the logic queries platform data or requires custom transformation that does not fit a gateway.
Using a source in a form
A producer can be embedded in an OBJECT_FORM_DASHBOARD as a SOURCE layout item. The user searches directly from the form, selects a result, and either an actor script is invoked or the selected fields prefill the form.
See Multi-step forms in the Layouts documentation for the full example and configuration options.