Webhooks for Billing Management

Automatically receive updates for Billing Management invoice events.

About webhooks for Billing Management

Billing Management can send webhook notifications to your system to keep you updated on the status of your invoices. These webhooks are sent out at key moments in the invoice lifecycle, allowing you to build powerful integrations and automate your workflows.

This document guides you through the steps to register your organization's webhook. To start, contact your Shipium representative to configure webhook notifications for your organization.

Who uses Billing Management webhooks

Billing Management webhooks are available to organizations using Shipium's Billing Management product. This includes:

  • 3PL organizations. Third-party logistics providers who manage shipping for multiple tenants and need to automate invoice delivery to their customers
  • Enterprise organizations. Large shippers who want automated notification when invoices are ready for processing in their internal systems

Your use case determines how webhooks are configured for your organization. Contact your Shipium representative to discuss your requirements and enable webhook notifications.

Webhook registration options

Your organization can register webhooks in the way that best fits your architecture:

Single endpoint for all events. Register one webhook endpoint to receive all invoice event types (invoice_created, invoice_finalized, invoice_voided). Your application then routes events internally based on the eventType field in the metadata.

Separate endpoints per event type. Register different webhook endpoints for each event type if you need events routed to different systems (for example, invoice_finalized events to your accounting system and invoice_created events to a review dashboard).

Tenant-specific routing (3PL organizations). If you manage multiple tenants, you can either:

  • register one webhook to receive notifications for all tenants and route them internally using the shipiumTenantId field, or
  • register separate webhooks for specific tenants with unique API endpoints.

Enterprise organizations typically register one webhook per internal system that needs to receive invoice notifications (for example, your accounting system or ERP).

Once you've registered your organization's webhook, you can disable, delete, and enable it in the Shipium Console. You also can view a summary of all your registered webhooks within the console.

Steps to register your webhook

To receive these webhook notifications, you will need to configure a webhook endpoint in your Shipium account settings. Contact your Shipium representative with the following information:

  • Endpoint URL. The HTTPS URL where you want to receive webhook notifications; HTTP endpoints are not supported.
  • Event types. Which events you want to receive (invoice created, invoice finalized, invoice voided, or all three)
  • Custom headers. Any HTTP headers your endpoint requires for authentication or routing
  • Tenant scope. Whether you want to receive notifications for all tenants or specific tenants (for 3PL organizations managing multiple tenants)

Auto-cut invoices

Billing Management supports automatic invoice finalization through the auto-cut feature. When auto-cut is enabled for a billing schedule, invoices generated by that schedule automatically transition to APPROVED status, which triggers the invoice_finalized webhook.

Auto-cut can be configured at the schedule level or overridden for specific tenants. Contact your Shipium representative to enable auto-cut for your billing schedules.

Invoice event types for your webhook

The following table includes the event metadata event types that can be returned for an invoice event notification. You can register a single webhook endpoint to receive all event types, or register separate endpoints for specific events based on your integration needs.

Event type for webhookTriggerPurpose
invoice_createdInvoice generated in DRAFT statusNotification that a new invoice is ready for review
invoice_finalizedInvoice approved and finalizedData delivery with presigned URL for CSV download
invoice_voidedInvoice canceled/voidedNotification that an invoice has been canceled

Invoice lifecycle

The following table shows when each webhook event is triggered during the invoice lifecycle.

Invoice statusTransitions toWebhook event trigger
DRAFTPENDING_APPROVAL or CANCELEDinvoice_created
PENDING_APPROVALAPPROVED or CANCELED(no event)
APPROVEDCANCELEDinvoice_finalized
CANCELEDinvoice_voided

Webhook message structure

All billing webhooks use a standard envelope structure with metadata and payload.

{
  "metadata": { ... },
  "payload": { ... }
}
FieldTypeRequiredDescription
metadataObjectYesEvent metadata for routing and idempotency
payloadObjectYesEvent-specific data (varies by event type)

Event metadata

The metadata object is identical across all event types.

FieldTypeRequiredDescription
eventIdString (UUID)YesUnique identifier for idempotency handling. Use this to prevent duplicate processing.
eventTimestampString (ISO 8601)YesUTC timestamp when the event was generated
eventTypeStringYesOne of: invoice_created, invoice_finalized, invoice_voided
partnerIdString (UUID)YesPartner identifier for routing
payloadSchemaVersionStringYesSchema version (currently v1)
testEventBooleanYesTrue if this is a test event (should not be processed as real data)

Invoice payload

The payload object contains invoice details. The following fields are included in all event types.

FieldTypeRequiredDescription
shipiumInvoiceIdString (UUID)YesUnique Shipium invoice identifier. Use this for API calls.
partnerInvoiceIdStringNoPartner's internal invoice reference (if assigned)
shipiumTenantIdString (UUID)NoShipium tenant identifier. null for partner-level invoices.
partnerTenantIdStringNoPartner's external tenant identifier
invoiceNumberStringYesHuman-readable invoice number for display
invoiceStatusStringYesCurrent status: draft, finalized, or voided
invoiceStartDateString (ISO 8601)YesStart of billing period
invoiceEndDateString (ISO 8601)YesEnd of billing period
invoiceDateString (ISO 8601)YesDate invoice was generated
invoiceDueDateString (ISO 8601)YesPayment due date (typically invoice date + 15 days)
currencyCodeStringYesISO 4217 currency code (e.g., USD)
invoiceTotalAmountNumberYesTotal invoice amount in the specified currency
totalTransactionCountIntegerYesNumber of carrier transactions (shipments) in this invoice

Invoice finalized payload fields

The invoice_finalized event includes additional fields for downloading the invoice CSV file.

FieldTypeRequiredDescription
presignedUrlString (URL)YesTime-limited URL to download the invoice CSV from S3
presignedUrlExpiresAtString (ISO 8601)YesTimestamp when the presigned URL expires
fileHashSha256StringYesSHA-256 hash of the CSV file for integrity verification
fileSizeBytesIntegerYesSize of the CSV file in bytes

Presigned URL details:

  • Expiration. URLs expire 24 hours after generation.
  • Regeneration. If the URL expires, request a new one using the regenerate presigned URL endpoint.
  • Integrity. Verify the downloaded file by comparing its SHA-256 hash against fileHashSha256.

Downloading invoice data

When an invoice is finalized, Shipium exports the invoice data to a CSV file and provides a presigned S3 URL in the webhook payload. Use this URL to download the complete invoice data, including all carrier transactions.

Downloading the CSV file. The presignedUrl field contains a time-limited URL for downloading the invoice CSV. The URL is valid until the timestamp specified in presignedUrlExpiresAt.

Verifying file integrity. After downloading the file, compare its SHA-256 hash against the fileHashSha256 value to verify the file was not corrupted during transfer.

Handling expired URLs. If the presigned URL has expired, use the regenerate presigned URL endpoint to obtain a new URL.

Webhook delivery failure. In rare cases where the S3 export fails, the invoice_finalized webhook may not be sent. If you expect an invoice to be finalized but do not receive a webhook, use the regenerate presigned URL endpoint or the CSV export endpoint as a fallback.

Invoice CSV file format

The CSV file downloaded via the presignedUrl contains one row per shipment (carrier transaction).

ColumnHeader nameData typeDescription
1TenantStringTenant name (or partner name for partner-level invoices)
2Invoice Generation DateDate (YYYY-MM-DD)Date the invoice was generated
3Invoice IDString (UUID)Unique invoice identifier
4Ship DateDate (YYYY-MM-DD)Date the shipment was shipped
5OriginStringOrigin postal code
6Currency CodeStringISO 4217 currency code (e.g., USD)
7Billing CostDecimalInvoice cost for this shipment
8Billable WeightDecimalBillable weight used for rating
9Billable Weight UnitStringWeight unit: LB (pounds) or KG (kilograms)
10Tracking NumberStringCarrier tracking number
11CarrierStringCarrier identifier (e.g., UPS, FEDEX, DHL)
12Carrier ZoneStringCarrier billing zone
13Carrier Invoice DateDate (YYYY-MM-DD)Date from carrier's invoice
14Service LevelStringCarrier service level (e.g., GROUND, EXPRESS)

Example CSV content:

Tenant,Invoice Generation Date,Invoice ID,Ship Date,Origin,Currency Code,Billing Cost,Billable Weight,Billable Weight Unit,Tracking Number,Carrier,Carrier Zone,Carrier Invoice Date,Service Level
Acme Corp,2025-12-04,inv-98765432-abcd-efgh-ijkl-mnopqrstuvwx,2025-11-15,90210,USD,12.50,5.2,LB,1Z999AA10123456784,UPS,4,2025-11-20,GROUND
Acme Corp,2025-12-04,inv-98765432-abcd-efgh-ijkl-mnopqrstuvwx,2025-11-16,10001,USD,18.75,3.8,LB,1Z999AA10123456785,UPS,6,2025-11-21,EXPRESS
Acme Corp,2025-12-04,inv-98765432-abcd-efgh-ijkl-mnopqrstuvwx,2025-11-16,60601,USD,9.25,2.1,LB,794644790299,FEDEX,2,2025-11-21,GROUND

File characteristics:

  • Encoding. UTF-8
  • Line ending. CRLF (\r\n)
  • Quoting. Fields containing commas, quotes, or newlines are quoted.
  • Header row. Always included as the first row
  • Sorting. Rows are not guaranteed to be in any particular order.

Partner-level vs tenant-level invoices

Tenant-level invoices

Standard invoices generated for a specific tenant within a partner account:

  • shipiumTenantId: Contains the tenant UUID
  • Tenant column in CSV: Contains the tenant name

Partner-level invoices

Aggregated invoices that combine all shipments across all tenants for a partner:

  • shipiumTenantId: null
  • Tenant column in CSV: Contains the partner name

API endpoints reference

Regenerate presigned URL

If a presigned URL has expired or you did not receive the invoice_finalized webhook, use this endpoint to generate a new presigned URL for downloading the invoice CSV.

Endpoint. POST /api/v1/billing/invoices/{invoiceId}/regenerate-presigned-url

Path parameters

ParameterTypeRequiredDescription
invoiceIdStringYesThe Shipium invoice ID

Response (200 OK)

{
  "presignedUrl": "https://shipium-billing-management-partner-invoices.s3.us-west-2.amazonaws.com/exports/invoices/...",
  "presignedUrlExpiresAt": "2026-01-16T18:00:00Z",
  "fileHashSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "fileSizeBytes": 1048576
}

Error responses

Status codeDescription
404 Not FoundThe invoice or the export for the invoice was not found.
400 Bad RequestThe presigned URL could not be regenerated; the response body contains error details.

Get invoice details

Returns full invoice details including line items:

Endpoint. GET /api/v1/billing/invoices/{invoiceId}

Path parameters

ParameterTypeRequiredDescription
invoiceIdStringYesThe Shipium invoice ID

Export invoice to CSV

Alternative endpoint to download invoice data as CSV (does not require webhook):

Endpoint. GET /api/v1/billing/invoices/{invoiceId}/export-csv

Path parameters

ParameterTypeRequiredDescription
invoiceIdStringYesThe Shipium invoice ID

Sample webhook payloads

The following examples show complete webhook messages for each event type.

Sample invoice_created payload

{
  "metadata": {
    "eventId": "evt-12345678-abcd-efgh-ijkl-mnopqrstuvwx",
    "eventTimestamp": "2025-12-04T14:30:00.000Z",
    "eventType": "invoice_created",
    "partnerId": "7b9c8d6e-5f4a-4321-b0c9-8e7f6a5b4c3d",
    "payloadSchemaVersion": "v1",
    "testEvent": false
  },
  "payload": {
    "shipiumInvoiceId": "inv-98765432-abcd-efgh-ijkl-mnopqrstuvwx",
    "partnerInvoiceId": null,
    "shipiumTenantId": "ab815bcc-950a-4902-ad8c-ac5ff6d9a438",
    "partnerTenantId": null,
    "invoiceNumber": "inv-98765432-abcd-efgh-ijkl-mnopqrstuvwx",
    "invoiceStatus": "draft",
    "invoiceStartDate": "2025-11-01T00:00:00Z",
    "invoiceEndDate": "2025-11-30T23:59:59Z",
    "invoiceDate": "2025-12-04T00:00:00Z",
    "invoiceDueDate": "2025-12-19T00:00:00Z",
    "currencyCode": "USD",
    "invoiceTotalAmount": 15847.92,
    "totalTransactionCount": 2847
  }
}

Use case. You can use this event to receive notification that a new invoice is ready for review, trigger internal workflows for invoice validation, and update dashboards with pending invoice information.

📘

This event does not include transaction-level details. To retrieve full invoice data, use the Invoice API or wait for the invoice_finalized event.

Sample invoice_finalized payload

{
  "metadata": {
    "eventId": "evt-12345678-abcd-efgh-ijkl-mnopqrstuvwx",
    "eventTimestamp": "2025-12-04T14:30:00.000Z",
    "eventType": "invoice_finalized",
    "partnerId": "7b9c8d6e-5f4a-4321-b0c9-8e7f6a5b4c3d",
    "payloadSchemaVersion": "v1",
    "testEvent": false
  },
  "payload": {
    "shipiumInvoiceId": "inv-98765432-abcd-efgh-ijkl-mnopqrstuvwx",
    "partnerInvoiceId": null,
    "shipiumTenantId": "ab815bcc-950a-4902-ad8c-ac5ff6d9a438",
    "partnerTenantId": null,
    "invoiceNumber": "inv-98765432-abcd-efgh-ijkl-mnopqrstuvwx",
    "invoiceStatus": "finalized",
    "invoiceStartDate": "2025-11-01T00:00:00Z",
    "invoiceEndDate": "2025-11-30T23:59:59Z",
    "invoiceDate": "2025-12-04T00:00:00Z",
    "invoiceDueDate": "2025-12-19T00:00:00Z",
    "currencyCode": "USD",
    "invoiceTotalAmount": 15847.92,
    "totalTransactionCount": 2847,
    "presignedUrl": "https://shipium-billing-management-partner-invoices.s3.us-west-2.amazonaws.com/exports/invoices/7b9c8d6e.../2025/12/inv-98765432.../invoice_inv-98765432..._20251204T143000Z.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&...",
    "presignedUrlExpiresAt": "2025-12-05T14:30:00Z",
    "fileHashSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "fileSizeBytes": 1048576
  }
}

Use case. You can use this event to download the complete invoice data for processing, trigger payment workflows in accounting systems, archive finalized invoices, and reconcile billing records.

Sample invoice_voided payload

{
  "metadata": {
    "eventId": "evt-12345678-abcd-efgh-ijkl-mnopqrstuvwx",
    "eventTimestamp": "2025-12-04T14:30:00.000Z",
    "eventType": "invoice_voided",
    "partnerId": "7b9c8d6e-5f4a-4321-b0c9-8e7f6a5b4c3d",
    "payloadSchemaVersion": "v1",
    "testEvent": false
  },
  "payload": {
    "shipiumInvoiceId": "inv-98765432-abcd-efgh-ijkl-mnopqrstuvwx",
    "partnerInvoiceId": null,
    "shipiumTenantId": "ab815bcc-950a-4902-ad8c-ac5ff6d9a438",
    "partnerTenantId": null,
    "invoiceNumber": "inv-98765432-abcd-efgh-ijkl-mnopqrstuvwx",
    "invoiceStatus": "voided",
    "invoiceStartDate": "2025-11-01T00:00:00Z",
    "invoiceEndDate": "2025-11-30T23:59:59Z",
    "invoiceDate": "2025-12-04T00:00:00Z",
    "invoiceDueDate": "2025-12-19T00:00:00Z",
    "currencyCode": "USD",
    "invoiceTotalAmount": 15847.92,
    "totalTransactionCount": 2847
  }
}

Use case. You can use this event to cancel pending payments for this invoice, update accounting systems to exclude the voided invoice, and maintain an audit trail of cancelled invoices.

Final steps and sample webhook call content

This section provides instructions for responding successfully to your webhook's initial call as well as information about Shipium's retry behavior.

How to respond to your webhook call

Upon receipt of a webhook call, respond with an appropriate HTTP status code to acknowledge successful receipt. Your response must be an HTTP status code within the 200-299 range.

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{"status": "received"}

Webhook retry logic

If a webhook delivery fails, the Shipium platform employs automated retry logic.

Retry policy:

  • Initial attempt. Immediate
  • Retry on failure. 1 retry after a brief delay
  • Timeout. Webhooks should respond within 30 seconds.

Failure handling. If webhook delivery fails after the retry, the event is logged but not requeued. Partners can use the Invoice API or the CSV export endpoint to retrieve invoice data.

Idempotency

Use the eventId field in the metadata to handle duplicate deliveries. Your system should track received event IDs and skip processing for events you have already handled.

def handle_webhook(event):
    event_id = event['metadata']['eventId']

    if already_processed(event_id):
        return {"status": "already_processed"}

    # Process the event
    process_event(event)

    # Mark as processed
    mark_processed(event_id)
    return {"status": "success"}

Test events

Filter out test events in production by checking the testEvent field in the metadata.

def handle_webhook(event):
    if event['metadata']['testEvent']:
        log.info("Ignoring test event")
        return {"status": "ignored_test_event"}

    # Process real event
    ...

File integrity verification

Verify downloaded CSV files using SHA-256 to ensure the file was not corrupted during transfer.

import hashlib

def verify_file(file_path, expected_hash):
    sha256 = hashlib.sha256()
    with open(file_path, 'rb') as f:
        for chunk in iter(lambda: f.read(8192), b''):
            sha256.update(chunk)
    return sha256.hexdigest() == expected_hash

Status mapping reference

The following table shows how internal invoice statuses map to webhook event types.

Internal statusWebhook statusEvent type
DRAFTdraftinvoice_created
PENDING_APPROVALpending(no event)
APPROVEDfinalizedinvoice_finalized
CANCELEDvoidedinvoice_voided

Troubleshooting

Webhook not receiving events

  • Confirm with your Shipium representative that your webhook is active.
  • Check that your endpoint URL is correct and accessible from the internet.
  • Ensure your endpoint responds within the 30-second timeout.
  • Verify firewall rules allow incoming requests from Shipium's infrastructure.

Duplicate events received

  • Implement idempotency handling using the eventId field.
  • Check if your endpoint is returning non-2xx responses, which triggers retries.

Presigned URL expired

Use the POST /api/v1/billing/invoices/{invoiceId}/regenerate-presigned-url endpoint to generate a new URL. URLs expire 24 hours after generation.

File hash mismatch after download

The file may have been corrupted during transfer. Re-download the file using the presigned URL or regenerate a new URL if it has expired. If the issue persists, contact Shipium Support.

Did not receive invoice_finalized webhook

In rare cases, the webhook may not be sent if the S3 export fails. Use the regenerate presigned URL endpoint or the CSV export endpoint (GET /api/v1/billing/invoices/{invoiceId}/export-csv) to retrieve the invoice data.

Missing tenant information

  • The shipiumTenantId and partnerTenantId fields are present for tenant-level invoices.
  • Partner-level invoices have null values for these fields.

Related documentation

Resources

Your Shipium team member is available to help along the way. However, you might find these resources helpful: