space.hooks.deliveries

List and read deliveries, send failed ones again, and cancel ones still waiting.

A delivery is one event on its way to one destination, with every attempt and the answer to each. It moves through these states:

StatusMeans
pendingWaiting for its first attempt, for the connection’s delay, the destination’s rate limit, or a paused destination
sendingAn attempt is on its way
retryingAn attempt failed, and the next one is due at dueAt
deliveredThe destination answered 2xx
failedEvery attempt failed, or the transformation failed
cancelledCancelled before it was sent

Sending a delivery again never changes it. It makes a new delivery of the same event to the same destination, with trigger set to resend. It is due at once, within the destination’s rate limit, and runs the connection’s current transformation. Its webhook-id header is the event’s ID, the same as the first time, so a receiver can tell it has seen the webhook before.

Deliveries are kept for 30 days with their events. 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.

space.hooks.deliveries.list()

Lists the project’s deliveries, newest first.

space.hooks.deliveries.list(filter?: {
  destinationId?: string
  status?: DeliveryStatus
  signal?: AbortSignal
  timeoutMs?: number
}): Paged<Delivery>
filter.destinationIdstring

Only the deliveries to this destination.

filter.statusDeliveryStatus

Only the deliveries in this state: pending, sending, retrying, delivered, failed, or cancelled.

filter.signalAbortSignal

Cancels the call when it aborts. The promise then rejects with aborted.

filter.timeoutMsnumber

The longest each request may take, in milliseconds. The client’s timeoutMs when you leave it out, 30,000 by default.

Returns a Paged<Delivery> at once, without a request. It reads the deliveries 200 at a time as you go: loop over it with for await, collect every one with .all(), or read one page with .page(cursor), which resolves to { items, nextCursor }.

destinationId and status 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.

failed-deliveries.ts
import { space } from "digitospace"

const failed = space.hooks.deliveries.list({
  destinationId: "01m3m5gpbttxs7xnhk0jgyt4wa",
  status: "failed",
})

for await (const delivery of failed) {
  console.log(delivery.id, delivery.lastStatusCode, delivery.lastError)
}

space.hooks.deliveries.get()

Reads one delivery, with every attempt and the request it sent.

space.hooks.deliveries.get(
  delivery: string,
  options?: {
    signal?: AbortSignal
    timeoutMs?: number
  }
): Promise<DeliveryDetail>
deliverystringRequired

The delivery’s ID, 26 lowercase letters and digits.

options.signalAbortSignal

Cancels the call when it aborts.

options.timeoutMsnumber

The longest each request may take, in milliseconds.

Returns a promise of the delivery with its attempts.

CodeWhen
validation_failedThe ID is not 26 lowercase letters and digits. Nothing is sent
not_foundThe project has no delivery with that ID, or it is more than 30 days old
get-delivery.ts
import { space } from "digitospace"

const delivery = await space.hooks.deliveries.get("01m3my2b448ze30bp4dhxfa4wd")

for (const attempt of delivery.attemptList) {
  console.log(attempt.number, attempt.statusCode, attempt.durationMs, attempt.error)
}

console.log(delivery.sent?.body)

space.hooks.deliveries.resend()

Sends one delivery, or up to 100, again. Each makes a new delivery, whatever state the one you name is in.

space.hooks.deliveries.resend(
  delivery: string | readonly string[],
  options?: {
    signal?: AbortSignal
    timeoutMs?: number
  }
): Promise<number>
deliverystring | readonly string[]Required

One delivery’s ID, or a list of 1 to 100 IDs.

options.signalAbortSignal

Cancels the call when it aborts.

options.timeoutMsnumber

The longest each request may take, in milliseconds.

Returns a promise of how many deliveries were made. For one ID, that is always 1. For a list, IDs the project has no delivery for are skipped, so the count can be lower than the list. The call is not sent again after a network failure or a timeout, because the deliveries may already have been made.

CodeWhen
validation_failedAn ID is not 26 lowercase letters and digits, or the list is empty or longer than 100. Nothing is sent
not_foundOne ID was given, and the project has no delivery with it
resend-deliveries.ts
import { space } from "digitospace"

await space.hooks.deliveries.resend("01m3my2b448ze30bp4dhxfa4wd")

const failed = await space.hooks.deliveries
  .list({ status: "failed", destinationId: "01m3m5gpbttxs7xnhk0jgyt4wa" })
  .page()

const resent = await space.hooks.deliveries.resend(
  failed.items.slice(0, 100).map((delivery) => delivery.id)
)

console.log(`Sent ${resent} again`)

space.hooks.deliveries.resendFailed()

Sends every failed delivery again once, in the whole project or to one destination. A failed delivery that was already sent again, by hand or by an earlier call, is skipped, so calling it twice does not send a webhook twice.

space.hooks.deliveries.resendFailed(options?: {
  destinationId?: string
  signal?: AbortSignal
  timeoutMs?: number
}): Promise<number>
options.destinationIdstring

Only the failed deliveries to this destination. Every destination in the project when you leave it out.

options.signalAbortSignal

Cancels the call when it aborts.

options.timeoutMsnumber

The longest each request may take, in milliseconds.

Returns a promise of how many deliveries were made, at most 1,000 in one call. When it returns 1,000, call it again for the rest. The call is not sent again after a network failure or a timeout, because the deliveries may already have been made.

CodeWhen
validation_faileddestinationId is not 26 lowercase letters and digits. Nothing is sent
resend-failed.ts
import { space } from "digitospace"

const destinationId = "01m3m5gpbttxs7xnhk0jgyt4wa"

await space.hooks.destinations.update(destinationId, {
  url: "https://orders.example.co.tz/webhooks/v2/payments",
})

const resent = await space.hooks.deliveries.resendFailed({ destinationId })

console.log(`Sent ${resent} failed payment webhooks again`)

space.hooks.deliveries.cancel()

Cancels a delivery that is still waiting, so it is never sent. A delivery is waiting while it is pending or retrying.

space.hooks.deliveries.cancel(
  delivery: string,
  options?: {
    signal?: AbortSignal
    timeoutMs?: number
  }
): Promise<Delivery>
deliverystringRequired

The delivery’s ID.

options.signalAbortSignal

Cancels the call when it aborts.

options.timeoutMsnumber

The longest each request may take, in milliseconds.

Returns a promise of the delivery, with status set to cancelled.

CodeWhen
validation_failedThe ID is not 26 lowercase letters and digits. Nothing is sent
not_foundThe project has no delivery with that ID
delivery_not_waitingThe delivery is being sent, or it has already finished
cancel-delivery.ts
import { SpaceError, space } from "digitospace"

try {
  await space.hooks.deliveries.cancel("01m3my2b448ze30bp4dhxfa4wd")
} catch (error) {
  if (error instanceof SpaceError && error.code === "delivery_not_waiting") {
    console.log("Too late to cancel: it is on its way or already finished")
  } else {
    throw error
  }
}

Last updated