space.hooks.connections
Join sources to destinations, with a filter, a delay, and a transformation.
A connection sends the webhooks a source receives to one destination. A source can have many connections, so one webhook can go to several destinations, and a destination can take webhooks from several sources.
When a webhook arrives, each enabled connection of its source checks its filter. Each one that matches makes a delivery to its destination, due after the connection’s delay. An event that no connection took is filtered.
A project holds at most 200 connections. Every call below can also fail with the codes shared by all of space, such as missing_project, forbidden, timeout, or network_error. See SpaceError.
Filters
A filter is a JSON object that says which webhooks the connection takes. It matches on four parts of the webhook as it was received:
body, parsed as JSON, or as text when it is not JSONheaders, with names in lower casequery, the query string’s values by namepath, the part of the URL after the source’s address
A plain value matches an equal value, and an object matches field by field, so the fields you leave out can hold anything. For other tests, use an object of operators in place of a value: $eq, $neq, $in, $nin, $gt, $gte, $lt, $lte, $exists, $startsWith, $endsWith, and $contains. $and, $or, and $not combine conditions. One object holds either operators or field names, not both.
{
"headers": { "x-provider": { "$in": ["mpesa", "airtel-money"] } },
"body": {
"status": "COMPLETED",
"amount": { "$gte": 10000 },
"msisdn": { "$startsWith": "25574" }
}
}A filter is at most 16 KB and 16 levels deep, and it is checked when the connection is saved. No filter, or null, takes every webhook.
Transformations
A transformation is JavaScript that changes a webhook before it is sent. It defines a function transform(request), which may be async, and returns the headers and body to send:
function transform(request) {
const payment = request.body
return {
headers: { "x-order-id": payment.reference },
body: {
orderId: payment.reference,
amountTzs: payment.amount,
phone: payment.msisdn,
paidAt: payment.timestamp,
},
}
}request holds method, path, query as a string, headers with names in lower case, and body: the parsed JSON when it is JSON, text otherwise, or base64 with bodyEncoding: "base64" when it is neither.
The object it returns replaces the webhook’s headers and body. headers is an object of at most 100 names and values. body is sent as JSON when it is an object or an array, with Content-Type: application/json unless you set one; as text when it is a string; and as bytes when it is a base64 string and you also return bodyEncoding: "base64". The destination’s authentication and signing headers are added as usual.
- When it runs. Filters see the webhook as it was received. The transformation runs on a delivery’s first attempt, and what it returns is kept, so every retry sends the same request. Sending a delivery again runs the connection’s current transformation, so a fixed transformation applies to failed webhooks you send again.
- What it can do. It runs for at most 100 ms with at most 128 MB of memory. It cannot fetch, read files, use timers, or import modules.
console.loglines are kept forspace.hooks.transformations.validate(). - When it fails. A transformation that throws, returns the wrong shape, or runs out of time or memory fails its delivery at once, with the reason in
lastError. It does not count against the destination.
The code is at most 64 KB. Saving a connection refuses code that does not parse or defines no transform.
space.hooks.connections.create()
Connects a source to a destination.
space.hooks.connections.create(
connection: ConnectionInput,
options?: {
signal?: AbortSignal
timeoutMs?: number
}
): Promise<Connection>connection.sourceIdstringThe ID of a source in the project, 26 lowercase letters and digits.
connection.destinationIdstringThe ID of a destination in the project.
connection.statestringenabledorpaused.enabledwhen you leave it out. A paused connection makes no deliveries, and webhooks that arrive while it is paused are not sent through it later.connection.filterRecord<string, unknown> | nullWhich webhooks to take. See Filters. Every webhook when you leave it out or pass
null.connection.delaySecondsintegerHow long to wait before the first attempt, 0 to 86,400 seconds. 0 when you leave it out.
connection.transformationstring | nullJavaScript that defines
transform(request), at most 64 KB. See Transformations. None when you leave it out or passnull.options.signalAbortSignalCancels the call when it aborts. The promise then rejects with
aborted.options.timeoutMsnumberThe longest each request may take, in milliseconds. The client’s
timeoutMswhen you leave it out, 30,000 by default.
Returns a promise of the new connection. create() is not sent again after a network failure or a timeout, because the connection may already exist.
| Code | When |
|---|---|
validation_failed | A field breaks a rule above or is not listed, the source or destination is not in the project, the filter cannot be read, or the transformation cannot run. issues names each field |
hooks_limit_reached | The project already holds 200 connections |
import { space } from "digitospace"
const connection = await space.hooks.connections.create({
sourceId: "01m3m5gpkrvj4qdxwkde3vt4w9",
destinationId: "01m3m5gpbttxs7xnhk0jgyt4wa",
filter: {
body: { status: "COMPLETED", amount: { $gte: 1000 } },
},
delaySeconds: 5,
})
console.log(connection.id)space.hooks.connections.get()
Reads one connection.
space.hooks.connections.get(
connection: string,
options?: {
signal?: AbortSignal
timeoutMs?: number
}
): Promise<Connection>connectionstringThe connection’s ID, 26 lowercase letters and digits.
options.signalAbortSignalCancels the call when it aborts.
options.timeoutMsnumberThe longest each request may take, in milliseconds.
Returns a promise of the connection.
| Code | When |
|---|---|
validation_failed | The ID is not 26 lowercase letters and digits. Nothing is sent |
not_found | The project has no connection with that ID |
import { space } from "digitospace"
const connection = await space.hooks.connections.get("01m3m5hezf7epksb7f8qbww4wb")
console.log(connection.filter, connection.transformation !== null)space.hooks.connections.list()
Lists the project’s connections, newest first: all of them, or those of one source or destination.
space.hooks.connections.list(filter?: {
sourceId?: string
destinationId?: string
signal?: AbortSignal
timeoutMs?: number
}): Paged<Connection>filter.sourceIdstringOnly the connections from this source.
filter.destinationIdstringOnly the connections to this destination.
filter.signalAbortSignalCancels the call when it aborts.
filter.timeoutMsnumberThe longest each request may take, in milliseconds.
Returns a Paged<Connection> at once, without a request. It reads the connections 200 at a time as you go: loop over it with for await, collect every connection with .all(), or read one page with .page(cursor), which resolves to { items, nextCursor }.
The IDs are checked when the list is read, not when you call list(). A wrong one rejects the first read with validation_failed, and nothing is sent.
import { space } from "digitospace"
const connections = await space.hooks.connections
.list({ sourceId: "01m3m5gpkrvj4qdxwkde3vt4w9" })
.all()
console.log(`${connections.length} destinations take these payments`)space.hooks.connections.update()
Changes some of a connection’s fields and keeps the rest. It reads the connection first, then saves it whole with your changes, so two updates at the same time can undo each other.
space.hooks.connections.update(
connection: string,
change: Partial<ConnectionInput>,
options?: {
signal?: AbortSignal
timeoutMs?: number
}
): Promise<Connection>connectionstringThe connection’s ID.
changePartial<ConnectionInput>The fields to change, with the same rules as
create(). A field you leave out keeps its value.filter: nullremoves the filter, andtransformation: nullremoves the transformation.options.signalAbortSignalCancels the call when it aborts.
options.timeoutMsnumberThe longest each request may take, in milliseconds.
Returns a promise of the changed connection. A new filter or delay applies to webhooks that arrive afterwards. A new transformation applies to every delivery that has not had its first attempt yet, and to deliveries sent again.
| Code | When |
|---|---|
validation_failed | A field breaks a rule, the source or destination is not in the project, the filter cannot be read, or the transformation cannot run. issues names each field |
not_found | The project has no connection with that ID |
import { space } from "digitospace"
await space.hooks.connections.update("01m3m5hezf7epksb7f8qbww4wb", {
transformation: `function transform(request) {
return {
headers: {},
body: { orderId: request.body.reference, amountTzs: request.body.amount },
}
}`,
})
await space.hooks.connections.update("01m3m5hezf7epksb7f8qbww4wb", {
transformation: null,
})space.hooks.connections.pause()
Pauses a connection. It makes no deliveries while it is paused, and webhooks that arrive in the meantime are not sent through it later. Deliveries it already made carry on.
space.hooks.connections.pause(
connection: string,
options?: {
signal?: AbortSignal
timeoutMs?: number
}
): Promise<Connection>connectionstringThe connection’s ID.
options.signalAbortSignalCancels the call when it aborts.
options.timeoutMsnumberThe longest each request may take, in milliseconds.
The same as update(connection, { state: "paused" }), with the same errors. Returns a promise of the paused connection.
import { space } from "digitospace"
await space.hooks.connections.pause("01m3m5hezf7epksb7f8qbww4wb")space.hooks.connections.resume()
Enables a paused connection. Webhooks that arrive from then on are sent through it.
space.hooks.connections.resume(
connection: string,
options?: {
signal?: AbortSignal
timeoutMs?: number
}
): Promise<Connection>connectionstringThe connection’s ID.
options.signalAbortSignalCancels the call when it aborts.
options.timeoutMsnumberThe longest each request may take, in milliseconds.
The same as update(connection, { state: "enabled" }), with the same errors. Returns a promise of the enabled connection.
import { space } from "digitospace"
await space.hooks.connections.resume("01m3m5hezf7epksb7f8qbww4wb")space.hooks.connections.delete()
Deletes a connection. Its source and destination stay, and deliveries it already made carry on, with connectionId set to null. Those that have not had their first attempt yet are sent without its transformation. This cannot be undone.
space.hooks.connections.delete(
connection: string,
options?: {
signal?: AbortSignal
timeoutMs?: number
}
): Promise<void>connectionstringThe connection’s ID.
options.signalAbortSignalCancels the call when it aborts.
options.timeoutMsnumberThe longest each request may take, in milliseconds.
Returns a promise that resolves when the connection is gone.
| Code | When |
|---|---|
validation_failed | The ID is not 26 lowercase letters and digits. Nothing is sent |
not_found | The project has no connection with that ID |
import { space } from "digitospace"
await space.hooks.connections.delete("01m3m5hezf7epksb7f8qbww4wb")Last updated