When a customer disputes a charge, an integration silently breaks, or a compliance reviewer asks "who changed this and when," you need a chain of evidence that spans your logs, MonetizeKit's API responses, and the workspace's Audit Log. Every layer of that chain is connected by IDs — this guide shows how to propagate and use them.
Every response carries a request ID
Every REST response — success or error — includes an X-Request-Id header. Supply your own value and it's echoed back exactly; omit it and MonetizeKit generates a UUID v4 for you. Log this value at the call site so it's the join key between your application logs and any downstream investigation.
curl -i \ -H "Authorization: Bearer $MONETIZEKIT_API_KEY" \ "$MONETIZEKIT_BASE_URL/plans?page=1&pageSize=1" \ | rg -i "^x-request-id:"# X-Request-Id: 7c2f6e1a-0e3b-4b9a-9a9f-8e2c9e6f0d21curl -i \ -H "Authorization: Bearer $MONETIZEKIT_API_KEY" \ -H "X-Request-Id: my-trace-9f2c1a" \ "$MONETIZEKIT_BASE_URL/plans?page=1&pageSize=1" \ | rg -i "^x-request-id:"# X-Request-Id: my-trace-9f2c1a -- echoed back exactly as sentconst requestId = `svc-${crypto.randomUUID()}`;const response = await fetch(`${baseUrl}/plans?page=1&pageSize=1`, { headers: { Authorization: `Bearer ${apiKey}`, "X-Request-Id": requestId, },});logger.info("monetizekit_call", { requestId, status: response.status });If a single user action fans out into three API calls (check an entitlement, record usage, create a subscription), give all three the same X-Request-Id prefix or a shared correlation field in your own logs. Tracing a single MonetizeKit request ID only gets you one leg of the journey.
Error responses include the same ID
Every error envelope — regardless of status code — nests code, message, and request_id under a single top-level error object (plus details for field-level validation errors). When a customer reports a failure, ask for error.request_id first; it's the fastest way to pull the exact request from logs without guessing at timestamps. Cross-reference error.code against the Error Codes reference for known causes and resolutions before escalating.
{ "error": { "code": "NOT_FOUND", "message": "Customer not found: cust_dev_9999", "request_id": "7c2f6e1a-0e3b-4b9a-9a9f-8e2c9e6f0d21" }}Correlate with the Audit Log
The workspace Audit Log (Enterprise mode, under /audit in the dashboard) is the compliance-grade record of security-relevant actions: CRUD on governed resources, authentication events, approval decisions, and data exports. Each entry records an actor, an actor type, an IP address, the affected resource, and free-form metadata — cross-reference the metadata against the request IDs and delivery IDs you logged on your side.
Action categories
| Action | Meaning |
|---|---|
create / update / delete | CRUD on a governed resource (contract, plan, API key, customer, workspace, etc.). |
login / logout | Session-level authentication events for dashboard users. |
approve / reject | Decisions on an approval workflow (e.g. a contract or override request). |
transfer | Ownership changes — workspace transfer, credit wallet reassignment. |
read / export | Sensitive reads and data exports, including audit log CSV exports themselves. |
Actor types
| Actor | Meaning |
|---|---|
user | A dashboard user acting through the UI. |
api_key | A REST/GraphQL call authenticated with a service token. |
webhook | An inbound integration (e.g. a Stripe webhook) that triggered a state change. |
system | An automated internal process (scheduled jobs, reconciliation). |
integration | A connected third-party integration acting on the workspace's behalf. |
Correlate webhook deliveries
Webhook-triggered changes appear in the Audit Log with actorType: "webhook". Log the delivery's X-MonetizeKit-Delivery ID (see the Webhooks guide ) alongside the audit entry's timestamp and resource ID — together they let you prove exactly which delivery attempt caused which downstream state change, which is essential when disputing whether an event was processed once or twice. The same correlation strategy applies to disputed usage events — see the Usage Metering Best Practices guide for the reconciliation job that catches drift before an invoice does.
Exporting for external review
Pull audit entries programmatically with GET /audit (scope audit:view) — the same API-key auth, rate limiting, and X-Request-Id/error-envelope handling as every other REST call in this guide.
curl -s \ -H "Authorization: Bearer $MONETIZEKIT_API_KEY" \ "$MONETIZEKIT_BASE_URL/audit"# { "data": [ { "id": "...", "timestamp": "...", "actor": "...", "actorType": "...",# "actorIp": "...", "action": "...", "resource": "...", "resourceId": "...",# "description": "...", "metadata": { ... } }, ... ] }REST API (programmatic, most recent 500)
GET /audit returns the workspace's 500 most recent entries, newest first — there's no query-param filtering or pagination yet, so page further back or filter by actor/action/date in the dashboard instead. It isn't listed in the API Reference explorer because of that limited surface, but the endpoint itself is fully functional today.
CSV export (bulk, filtered)
The Audit Log page's "Export CSV" action exports the currently filtered entries — narrow the filters first (actor, action, date range) so the export matches the scope of your review, then hand the file to a compliance team or archive it externally.
If your compliance workflow needs continuous, real-time ingestion into a SIEM rather than periodic polling of GET /audit or manual CSV export, that's not a built-in feature today — drive interim alerting off request IDs and webhook delivery correlation as described above.
Common pitfalls
Not logging the request ID at the call site
If you only discover you need a request ID after an incident, it's too late — log it on every call, success and failure alike, from day one.
Reusing one request ID across retries
A retried call is a distinct request. Reusing the same X-Request-Id across retries makes it impossible to tell, from the ID alone, whether a request succeeded on the first or third attempt.
Exporting unfiltered audit data
CSV exports are themselves an export action recorded in the log. Filter to the minimum necessary scope before exporting, both for review clarity and for data-minimization compliance requirements.
Assuming the audit API paginates
GET /audit has no page/cursor params — it always returns the 500 most recent entries. Don't build automation that assumes it can page through the full history; use the dashboard's date-range filters and CSV export for anything older.
FAQ
Can I set my own X-Request-Id and have it accepted?
Yes — any non-empty string is accepted and echoed back verbatim. If you omit the header, MonetizeKit generates a UUID v4 for you and returns it, so the header is always present either way.
Does the audit log capture read-only API calls?
Sensitive reads (like revealing a webhook signing secret) are recorded as read actions. Routine, high-volume reads (entitlement checks, usage lookups) are not, to keep the log focused on security- and governance-relevant events rather than every API call.
How long is audit log data retained?
It's a per-workspace setting (Settings → Security → auditRetentionDays), defaulting to 365 days if unset. Whatever you configure is clamped to between 90 and 730 days — export data you need to retain longer than that via CSV export rather than assuming indefinite retention.
Related guides
Webhook Verification and Retries
Delivery IDs are the join key for webhook-triggered audit entries.
Migration Guide
Use request IDs to isolate errors introduced during a migration rollout.
Entitlement Evaluation Patterns
Overrides are auditable exceptions — see how they resolve.