---
title: "Replay a parked integration event"
method: POST
path: "/companies/{company}/integrations/events/{event}/replay"
tags: ["Integration Events"]
---

# Replay a parked integration event

`POST /companies/{company}/integrations/events/{event}/replay`

## Request

- Base URL: `https://api.factuarea.com/v1`
- URL: `https://api.factuarea.com/v1/companies/{company}/integrations/events/{event}/replay`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Reprocess a parked gateway event once the cause that parked it is fixed.
- Needs `integration_events:write`; the event must have `is_replayable: true`, otherwise 422.
- It can issue a real invoice with VeriFactu registration; confirm with the owner first.
- 202 means queued, not completed; the outcome arrives as a new event, and invoices are never duplicated.

## Path parameters

- `company` string, uuid, required
- `event` string, uuid, required

## Headers

- `Idempotency-Key` string, required
- `Factuarea-Version` string, date

## Response `202`

- object
  - `data` IntegrationEvent, required: One event a payment gateway sent to Factuarea, with the outcome it produced and, when it produced none, the typed reason why. Read-only and scoped to your own company. The raw content of the event is NEVER exposed: it carries personal data of your end customers and payment details, is stored encrypted only for parked events so they can be reprocessed, and is purged 30 days after being parked.
    - `id` string, uuid, required: UUID v7 of the event. Use it in `GET /v1/companies/{company}/integrations/events/{event}` and in the replay operation.
    - `object` 'integration_event', required: Always `integration_event`.
    - `provider` 'stripe' | 'gocardless' | 'monei' | 'slack' | 'teams' | 'a3' | 'norma43' | 'norma19' | 'ubl', required: Gateway or integration the event came from. Closed set, so it is safe to switch on it.
    - `event_type` string, required: Event type as reported by the provider, matched EXACTLY when you filter by it. Free-form text, NOT a closed enum: the field deliberately mixes the raw provider type (`charge.refunded`, `invoice.paid`) with the internal semantic value some older branches recorded (`autoinvoice.*`). Do not model it as a fixed catalogue — for a filterable, closed axis use `discard_reason`.
    - `direction` string, required: Direction of the exchange: `inbound` for something the provider sent us (all gateway webhooks), `outbound` for a call the platform made to the provider, `internal` for a state change of the integration itself. Free-form string rather than an enum: it is not backed by a closed catalogue in code.
    - `status` 'success' | 'skipped' | 'failure', required: Outcome of the event: `success` (it produced its effect), `skipped` (it was discarded on purpose — see `discard_reason`) or `failure` (it broke while being processed — see `error_message`).
    - `discard_reason` 'event_not_normalizable' | 'duplicate_redelivery' | 'connected_account_missing' | 'connected_account_unknown' | 'spontaneous_payment_missing_id' | 'autoinvoicing_disabled' | 'unsupported_currency' | 'refund_without_items' | 'refund_autoinvoicing_disabled' | 'subscription_missing_invoice_id' | 'subscription_proration_review' | 'subscription_not_a_cycle' | 'subscription_trial_skipped' | 'subscription_autoinvoicing_disabled' | 'subscription_already_invoiced' | 'payout_missing_id' | 'payout_connected_account_missing' | 'payment_failed' | 'event_type_not_covered' | 'checkout_lines_retrieve_failed' | 'reversal_payment_not_found' | 'reversal_already_applied' | 'dispute_in_progress' | 'dispute_resolved' | 'test_mode_event' | 'order_event_not_covered' | 'store_not_found' | 'store_environment_test' | 'refund_before_order' | 'refund_reason_unmapped' | 'recurring_invoice_overlap' | 'series_date_clamped' | 'store_autoinvoicing_disabled' | 'vat_residual_out_of_tolerance' | 'simplified_absolute_limit_exceeded' | 'simplified_threshold_exceeded_without_recipient' | 'store_requires_tax_id' | 'order_line_amount_exceeds_column' | 'order_status_unknown' | 'refund_not_settled' | 'protected_customer_data_unavailable' | 'excluded_by_charge_rule' | 'handled_by_stripe_invoice' | 'stripe_authorization_required' | 'stripe_app_uninstalled' | 'refund_of_non_invoiced_charge' | 'stripe_invoice_without_amount' | 'deauthorization_not_applicable' | 'null', nullable, required: Typed reason why the event was discarded, from a CLOSED catalogue, or `null` when it was not discarded. This is the axis to filter and group by. A value retired from the catalogue in a later version is still returned verbatim here, but its `discard_reason_label`, `is_actionable` and `is_replayable` degrade to neutral rather than breaking the page.
    - `discard_reason_label` string, nullable, required: Human-readable label of `discard_reason`, in Spanish (the platform's end-user language). `null` when there is no discard reason, or when the stored reason is no longer part of the current catalogue.
    - `is_actionable` boolean, required: `true` when the account owner can do something about this discard (turn a setting on, re-link an account). Only actionable discards notify the user; the informative ones are recorded but never interrupt anyone.
    - `is_replayable` boolean, required: CONTRACT of the replay operation: when it is `true`, `POST /v1/companies/{company}/integrations/events/{event}/replay` does not answer 422. It is the conjunction of three conditions — the event is parked, it still holds its content, and its discard reason admits reprocessing — evaluated by the same check that guards the replay. It turns to `false` on its own once the 30-day retention window purges the content, even though the event stays parked.
    - `error_message` string, nullable, required: Error raised while processing the event, or `null` when there was none. Relevant for `failure`; a `skipped` event carries its reason in `discard_reason`, not here.
    - `duration_ms` integer, nullable, required: Server-side processing time in milliseconds, or `null` when it was not measured.
    - `created_at` string, date-time, required: When the event was recorded (ISO 8601).
    - `recommended_action` string, nullable: Next step for this specific discard reason, in Spanish and in the imperative. Present ONLY in the detail and in the 202 of the replay — the listing omits it, because repeating the same sentence across 100 elements is noise. `null` when the reason is merely informative: if there is nothing to do, the contract does not invent an instruction. The sentence tells reproducible reasons ("… y reprocesa el evento") apart from the ones that are not ("… emítela a mano"), so it never points you at a call that would answer 422. When a reason admits BOTH ways out, they are worded as mutually exclusive and the sentence spells out the consequence of doing both: replay idempotency keys on the charge and only recognises invoices issued through that same automatic path, so an invoice created by hand does not stop it — doing both leaves two invoices for one charge, each numbered in its series and filed with VeriFactu.

## Other responses

- `400`: The request is syntactically malformed — e.g. an unknown query parameter, an integer parameter with non-numeric value, or a value outside the documented range.
- `401`: Missing or invalid API key.
- `403`: The request is authenticated but not allowed: the API key lacks the required scope (`insufficient_scope`), the plan does not include the public API or this feature (`addon_not_active`, `feature_not_available_in_plan`), or the module is not available with a test key (`module_not_available_in_sandbox`).
- `404`: The requested resource does not exist or belongs to another company.
- `422`: The integration event exists but cannot be replayed. All three cases share the code `business_rule_violation` and are told apart by `error.subcode`: `integration_event_not_parked` (it was never parked, so there is nothing to reprocess and there never will be), `integration_event_payload_purged` (it was parked, but its content was deleted when the 30-day retention window elapsed) and `integration_event_reason_not_replayable` (it is parked and still holds its content, but its discard reason would take exactly the same branch again). An event whose `is_replayable` is `true` never reaches this response.
- `429`: Rate limit exceeded. Retry after the duration in `Retry-After`.
- `500`: Unexpected server error.

---

[API](https://skmtc.dev/factuarea/apis/factuarea-public-api.md) · [All operations](https://skmtc.dev/factuarea/apis/factuarea-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/factuarea/apis/factuarea-public-api/revisions/718e77934422?raw)
