Wunder Mobility Data Exports allow you to receive scheduled bulk data from your fleet management platform as CSV files. When an export is ready, you are notified via email, webhook, or both, with a link to download the file.
Exports are configured by your Customer Success Manager (CSM), who sets up predefined reports tailored to your data needs (e.g., trip history, vehicle utilization, active users). This is distinct from the synchronous JSON export endpoints available in the Operations API (such as /customers/export and /rentals/export), which are designed for on-demand programmatic access.
Who This Guide Is For: Developers and technical teams integrating with Wunder Mobility’s scheduled data export system, particularly those building automated pipelines to ingest webhook-delivered CSV reports.
| Related Documentation: Wunder Operations API | API Basics |
| Type | Description |
|---|---|
| One-time export | Runs once at a scheduled time and delivers a single CSV file |
| Recurring export | Runs on a repeating schedule (e.g., every day at midnight) and delivers a new CSV file each time |
Export files are delivered as CSV (comma-separated values) with:
,) delimiterWhen an export completes, you receive an email containing a download link.
| Property | Details |
|---|---|
| Subject | {Your Organization} {Report Name} - {Date and Time} |
| Body | A short message with a clickable download link |
| From | Wunder Mobility system email address |
Click the “Export results” link in the email. This link redirects you to a temporary download URL for the CSV file.
Important: Download links are valid for 7 days after you receive the notification. After that, the link will no longer work.
If you have a webhook endpoint configured, Wunder Mobility sends an HTTP POST request to your URL each time an export completes successfully.
Not to be confused with Platform Webhooks: The platform webhooks deliver real-time event notifications (e.g., rental started, invoice created) and use a different payload format, different headers (
x-webhook-*), and HMAC-SHA1 signing. Data export webhooks described here follow the Standard Webhooks specification, usewebhook-*headers, and sign with HMAC-SHA256.
POST https://your-endpoint.example.com/webhook
Content-Type: application/json
{
"id": 42,
"queryId": 7,
"queryName": "Active Vehicles Report",
"exportUrl": "https://export.gourban.services/.../download?uuid=abc-123-def",
"expirationDate": "2026-03-01T14:30:00+01:00"
}
| Field | Type | Description |
|---|---|---|
id |
Number | Unique identifier of this export run |
queryId |
Number | Identifier of the report query |
queryName |
String | Human-readable name of the report |
exportUrl |
String | URL to download the CSV file (see Downloading the File) |
expirationDate |
String | ISO 8601 timestamp after which the file is no longer available |
The exportUrl in the webhook payload points to the download endpoint. When you make a GET request to this URL, you receive an HTTP 303 redirect to a temporary pre-signed download URL.
GET https://export.gourban.services/.../download?uuid=abc-123-def
303 See Other
Location: https://s3.amazonaws.com/...?X-Amz-Signature=...
Most HTTP clients follow redirects automatically, so a simple GET request will download the CSV file directly.
Two expiration levels apply:
exportUrl (the download endpoint in the payload) remains accessible until the expirationDate shown in the webhook payload. You can call it multiple times to generate fresh download links.Every webhook request includes the following HTTP headers:
| Header | Example | Description |
|---|---|---|
Content-Type |
application/json |
Payload format |
webhook-id |
a1b2c3d4-e5f6-... |
Unique identifier for this export. Stays the same across retries – use this to deduplicate deliveries |
x-webhook-dispatch-attempt-count |
1 |
Which delivery attempt this is (starts at 1) |
If authentication is enabled for your organization, additional headers are included:
| Header | Example | Description |
|---|---|---|
x-api-key |
f8e7d6c5-b4a3-... |
Your organization’s API key. Use this to verify the request is coming from Wunder Mobility |
webhook-timestamp |
1709042400 |
Unix timestamp (seconds) of when the webhook was sent. Used for signature verification |
webhook-signature |
v1,K7gNU3sdo+OL... |
HMAC-SHA256 signature of the payload. Used to verify message integrity |
Your CSM can provide you with your API key and signing key if you need them.
If your organization has a signing key configured, you can verify that webhook payloads are authentic and have not been tampered with.
The signature follows the Standard Webhooks specification.
webhook-id, webhook-timestamp, and webhook-signature headers from the request{webhook-id}.{webhook-timestamp}.{request-body}
Where {request-body} is the raw JSON body of the request
v1, in the webhook-signature headerimport hmac
import hashlib
import base64
def verify_webhook(headers, body, signing_key):
webhook_id = headers["webhook-id"]
timestamp = headers["webhook-timestamp"]
signature = headers["webhook-signature"]
# Construct signing content
signing_content = f"{webhook_id}.{timestamp}.{body}"
# Compute expected signature
key_bytes = base64.b64decode(signing_key)
expected = hmac.new(
key_bytes,
signing_content.encode("utf-8"),
hashlib.sha256
).digest()
expected_b64 = base64.b64encode(expected).decode("utf-8")
# Compare with received signature (strip "v1," prefix)
received_b64 = signature[3:] if signature.startswith("v1,") else signature
return hmac.compare_digest(expected_b64, received_b64)
const crypto = require("crypto");
function verifyWebhook(headers, body, signingKey) {
const webhookId = headers["webhook-id"];
const timestamp = headers["webhook-timestamp"];
const signature = headers["webhook-signature"];
// Construct signing content
const signingContent = `${webhookId}.${timestamp}.${body}`;
// Compute expected signature
const keyBytes = Buffer.from(signingKey, "base64");
const expected = crypto
.createHmac("sha256", keyBytes)
.update(signingContent)
.digest("base64");
// Compare with received signature (strip "v1," prefix)
const received = signature.replace("v1,", "");
const expectedBuf = Buffer.from(expected);
const receivedBuf = Buffer.from(received);
if (expectedBuf.length !== receivedBuf.length) {
return false;
}
return crypto.timingSafeEqual(expectedBuf, receivedBuf);
}
If your endpoint is unreachable (network error or timeout), delivery is retried up to 3 times with increasing delays:
| Attempt | Delay |
|---|---|
| 1st (initial) | Immediate |
| 2nd (retry) | ~10 seconds |
| 3rd (retry) | ~20 seconds |
| 4th (retry) | ~40 seconds |
The webhook-id header stays the same across all retry attempts, so you can use it to detect and ignore duplicate deliveries.
Note: If your endpoint returns an error response (e.g., HTTP 4xx or 5xx), the delivery is marked as failed and is not retried. Make sure your endpoint returns a 2xx status code to acknowledge successful receipt.
Your webhook endpoint should:
200 OK) to confirm receiptExport files are available for a limited time after generation. The retention period depends on how your export is configured:
| Retention Period | Duration |
|---|---|
| 1 day | 24 hours |
| 1 week | 7 days |
| 2 weeks | 14 days |
| 1 month | 30 days |
| Default | 31 days |
After the retention period, the file is permanently deleted and the exportUrl will no longer work. The expirationDate field in the webhook payload tells you exactly when this happens.
Note: Each time you call the exportUrl, it generates a pre-signed download URL that is valid for 7 days. If a pre-signed URL expires, you can simply call the exportUrl again to get a new one — as long as the file has not yet reached its expirationDate.
| Webhook | ||
|---|---|---|
| Triggered on | Export completed successfully | Export completed successfully |
| Contains | Download link | JSON payload with download URL, report name, and expiration date |
| Authentication | N/A | Optional API key and HMAC signature |
| Retries | Up to 4 total attempts | Up to 4 total attempts |
| Failure notification | Not sent if export fails | Not sent if export fails |
To configure data exports for your organization:
For questions or changes to your export configuration, reach out to your Customer Success Manager.
/customers/export, /rentals/export, /invoices/reports)