Added

Per-Entity Document Webhooks for Loads, Trips, Drivers, Carriers, Trucks & Trailers

What's New?

Twelve new webhook event types are now available on the Public API — two for each parent entity that exposes documents through the API. Whenever a document is uploaded or removed in Alvys, the platform emits a webhook to every active subscription that selected the corresponding event.

EventFires when
load.document.uploadedA new document is attached to a load
load.document.deletedA load document is soft-deleted
trip.document.uploadedA new document is attached to a trip
trip.document.deletedA trip document is soft-deleted
driver.document.uploadedA new document is attached to a driver
driver.document.deletedA driver document is soft-deleted
carrier.document.uploadedA new document is attached to a carrier
carrier.document.deletedA carrier document is soft-deleted
truck.document.uploadedA new document is attached to a truck
truck.document.deletedA truck document is soft-deleted
trailer.document.uploadedA new document is attached to a trailer
trailer.document.deletedA trailer document is soft-deleted

Events fire regardless of write source — UI uploads, Public API uploads, mobile-app uploads, EDI document ingestion, or third-party integrations all produce the same deliveries.

Every *.document.uploaded event ships with a short-lived pre-signed download URL (≤ 15-minute TTL) so partners can pull the file directly from blob storage without an additional API call.

What Changed?

Subscribing

In Settings → API → Webhooks → Create / Edit subscription, select any combination of the new event types. The full list is also returned by GET /p/v1.0/webhooks/event-types for programmatic configuration.

Envelope (general structure)

All document webhook deliveries share the standard envelope used by tender.*, load.status.changed, and trip.status.changed. id is the deterministic idempotency key ({documentId}-{etag}); etag is also exposed as its own top-level envelope field so consumers can detect out-of-order replays for the same documentId.

*.document.uploaded payload (general structure)

Real production sample (trip.document.uploaded):

{
  "id": "00000000-0000-0000-0000-000000000000-00000000-0000-0000-0000-000000000000",
  "type": "trip.document.uploaded",
  "timestamp": "2026-05-13T09:16:30.9797738+00:00",
  "version": "v1",
  "etag": "00000000-0000-0000-0000-000000000000",
  "data": {
    "tripId": "00000000000000000000000000000000",
    "document": {
      "id": "00000000-0000-0000-0000-000000000000",
      "attachmentPath": "bol.pdf",
      "attachmentType": "Bill of Lading",
      "attachmentSize": 10000,
      "uploadedAt": "2026-05-13T09:16:30.9797738+00:00",
      "parentId": "1000000",
      "parentType": "Trip",
      "uploadedBy": "00000000000000000000000000000000",
      "downloadUrl": "{url}",
      "expiresAt": "2026-05-13T09:26:35.3227049+00:00"
    }
  }
}
  • data.tripId is the trip GUID (the natural public identifier returned by GET /p/v1.0/trips/{tripId}).
  • data.document.parentId on a trip document is the load number ("1000000") — matching how trip documents are stored internally and returned by GET /loads/{loadNumber}/documents.
  • attachmentType is a human-readable Alvys document type (e.g. "Bill of Lading", "Proof of Delivery", "Rate Confirmation") — same value returned by the document Public API endpoints.
  • uploadedBy is the user id (GUID) of the uploader.

The same shape applies to the other five parent types — data always contains the parent's natural public identifier (loadNumber, tripId, driverId, carrierId, truckId, or trailerId) plus a document block. For example, driver.document.uploaded swaps tripId for driverId; the document block is identical.

*.document.deleted payload (general structure)

// load.document.deleted
{
  "id": "00000000-0000-0000-0000-000000000000-00000000-0000-0000-0000-000000000000",
  "type": "load.document.deleted",
  "timestamp": "2026-05-13T16:05:22.118+00:00",
  "version": "v1",
  "etag": "00000000-0000-0000-0000-000000000000",
  "data": {
    "loadNumber": "1000000",
    "document": {
      "id": "00000000-0000-0000-0000-000000000000",
      "attachmentPath": "bol.pdf",
      "attachmentType": "Bill of Lading",
      "attachmentSize": 10000,
      "uploadedAt": "2026-05-13T09:16:30.9797738+00:00",
      "uploadedBy": "00000000000000000000000000000000",
      "parentId": "1000000",
      "parentType": "Load"
    }
  }
}

downloadUrl and expiresAt are omitted on delete events — the document is logically gone, so consumers should not pull bytes.

Behavior notes

  • An event fires only when a document is created or soft-deleted — rename, retype, and other metadata-only edits do not generate deliveries.
  • Pre-signed downloadUrl is short-lived (≤ 15 minutes). Pull the file promptly, or fall back to GET /p/v1.0/{parent}/{parentId}/documents/{documentId} if it expires.

Endpoints Affected

Webhook subscription management

These existing endpoints now accept the twelve new event types in their eventTypes array:

  • GET /p/v1.0/webhooks/event-types — returns the full catalog including the new document event types.
  • POST /p/v1.0/webhooks — create a subscription that selects any combination of the new events.
  • PUT /p/v1.0/webhooks/{id} — update an existing subscription to add or remove document events.
  • GET /p/v1.0/webhooks/{id} — inspect which events a subscription is selecting.
  • GET /p/v1.0/webhooks/{id}/deliveries — delivery history for the new events flows through the same logs surface as tender.* and *.status.changed.

Document endpoints driving the events

Any write to the following document sub-resources will fire the corresponding webhook for active subscribers. No request or response shape has changed on these endpoints — they are listed here so you can correlate which API actions produce which events.

EndpointFires
POST /p/v1.0/loads/{loadNumber}/documentsload.document.uploaded
DELETE /p/v1.0/loads/{loadNumber}/documents/{documentId}load.document.deleted
POST /p/v1.0/trips/{tripId}/documentstrip.document.uploaded
DELETE /p/v1.0/trips/{tripId}/documents/{documentId}trip.document.deleted
POST /p/v1.0/drivers/{driverId}/documentsdriver.document.uploaded
DELETE /p/v1.0/drivers/{driverId}/documents/{documentId}driver.document.deleted
POST /p/v1.0/carriers/{carrierId}/documentscarrier.document.uploaded
DELETE /p/v1.0/carriers/{carrierId}/documents/{documentId}carrier.document.deleted
POST /p/v1.0/trucks/{truckId}/documentstruck.document.uploaded
DELETE /p/v1.0/trucks/{truckId}/documents/{documentId}truck.document.deleted
POST /p/v1.0/trailers/{trailerId}/documentstrailer.document.uploaded
DELETE /p/v1.0/trailers/{trailerId}/documents/{documentId}trailer.document.deleted

UI uploads, mobile-app uploads, EDI ingestion, and third-party integrations also produce the same events even though they don't go through the Public API endpoints above.

Fallback retrieval (if a downloadUrl expires)

If the 15-minute pre-signed downloadUrl expires before you fetch the file, retrieve the document through the standard authenticated endpoint:

GET /p/v1.0/{parent}/{parentId}/documents/{documentId}

Why?

Until now, retrieving newly uploaded documents required polling the document sub-resource on each parent — /loads/{loadNumber}/documents, /drivers/{driverId}/documents, and four more. With these events in place:

  • Real-time document automation — POD-driven invoice automation, factoring, document management, and EDI 210 invoice validation no longer wait on a poll loop.
  • 🔁 Lower API load — eliminates polling traffic against six different parent endpoints.
  • 🎯 Subscribe narrowly — events are scoped per entity (load.* vs driver.* vs carrier.* …). A factoring integration that only cares about load-side documents won't receive driver med-card updates.
  • 🧾 Built-in audit trail — every delivery attempt is recorded and visible in the Webhook details page.
  • 🔗 Direct download — every *.uploaded event carries a pre-signed download URL.

Who has access?

All Public API consumers with an active webhook subscription that selects any of the new event types. Subscription management requires Partner Admin / Admin / Support role under Settings → API → Webhooks.

Frequently Asked Questions (FAQ)

Q: Do I need a new credential or scope to receive these events? A: No. Existing webhook subscriptions can opt in by selecting the new event types.

Q: Is the downloadUrl reusable? A: It's a single short-lived pre-signed Azure Blob SAS — valid for up to 15 minutes from emission. If it expires, retrieve the document through the standard Public API endpoint instead.

Q: Are events ordered? A: Deliveries are best-effort ordered per document. Consumers should be idempotent and use the envelope id ({documentId}-{_etag}) as the idempotency key.

Q: Can I see delivery history for these events? A: Yes — the existing Logs sidebar on the webhook detail page shows every delivery attempt for these event types, with the same filtering, pagination, and CSV/JSON export as tender.* and status-change events.

Q: Are document update / rename events available? A: Not in this release. Today we emit on upload and soft-delete only. Update events may be added later as *.document.updated if there's customer demand.