---
title: "List integration events"
method: GET
path: "/companies/{company}/integrations/events"
tags: ["Integration Events"]
---

# List integration events

`GET /companies/{company}/integrations/events`

## Request

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

Browse everything the payment gateways have sent to Factuarea. This is the inbox to open when a charge did not generate its invoice: every discarded event carries a typed `discard_reason` and whether it can be reprocessed. Newest first, and scoped to the authenticated company. The raw content of the event is never returned.

## Path parameters

- `company` string, uuid, required

## Query parameters

- `provider` 'stripe' | 'gocardless' | 'monei' | 'slack' | 'teams' | 'a3' | 'norma43' | 'norma19' | 'ubl' | 'woocommerce' | 'shopify' | 'prestashop'
- `status` 'success' | 'skipped' | 'failure'
- `event_type` string
- `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'
- `is_parked` boolean
- `created_at[gte]` string, date-time
- `created_at[lte]` string, date-time
- `limit` integer
- `starting_after` string

## Headers

- `Factuarea-Version` string, date

## Response `200`

`IntegrationEventListV1Resource`

- object: Cursor-paginated page of integration events (`{ data, has_more, next_cursor }`), most recent first.
  - `data` object[], required: Page of integration events, newest first. The elements do NOT carry `recommended_action`: fetch the detail of the one you care about.
    - `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.
  - `has_more` boolean, required: `true` when more events exist beyond this page.
  - `next_cursor` string, nullable, required: Opaque cursor to pass as `starting_after` for the next page, or `null` when `has_more` is `false`. Unlike the rest of the v1 listings it is a numeric string, not a UUID v7 — treat it as opaque and reuse it verbatim.

## 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. `profile_not_found`: the company in the path does not exist, is not in the API key scope or belongs to the other environment (live or test).
- `422`: Validation failed. The `error.param` field identifies which input is invalid.
- `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)
