---
title: "Push held receipts to the ERP"
method: POST
path: "/v1/payments/erp-push"
tags: ["Payments"]
---

# Push held receipts to the ERP

`POST /v1/payments/erp-push`

## Request

- Base URL: `https://api.getfinero.com/functions/v1/api`
- URL: `https://api.getfinero.com/functions/v1/api/v1/payments/erp-push`
- Auth: HTTP bearer

Releases payments whose receipt is HELD (the connection's payment_push_mode is manual) so they are pushed to the ERP. One request releases up to 100 payments; the ERP still receives ONE receipt per payment, one call each, so a failure on one never affects the others and a payment already in the ERP is never posted twice. The answer is a verdict per payment id — ACCEPTANCE, not the ERP's outcome, which arrives afterwards: read each payment's `erp_push_status` (`posted` on success, `failed` with `erp_push_error_category` otherwise). `released` — it was held and is now being pushed. `already_pushed` — the ERP has it. `not_held` — nothing to release: it is queued, in flight, failed (retry is a separate admin action in the app), or has no receipt at all (a Finero-created invoice, payment sync switched off, or a payment before payment sync was enabled). `not_found` — not a payment in this workspace. Safe to repeat: a second request for the same ids answers `already_pushed` or `not_held`.

Requires an **admin** API key (has side effects).

## Request body

- object
  - `payment_ids` string[], required: Payment ids (from GET /v1/payments) to release. Duplicates are answered once.

## Response `202`

Success

- object: Accepted. Released receipts are pushed in the background, one call each.
  - `results` object[], required: One verdict per distinct payment id asked for.
    - `payment_id` string, uuid, required: The payment this verdict is about.
    - `verdict` 'released' | 'already_pushed' | 'not_held' | 'not_found', required: `released` is now being pushed; `already_pushed` the ERP has it; `not_held` nothing to release; `not_found` not a payment in this workspace.

## Other responses

- `400`: `validation_failed` — The request failed schema validation. See error.details for field messages.
- `401`: `invalid_credentials` — The credential is malformed or does not match an active key. The response never reveals whether a key identifier exists. `missing_credentials` — No Authorization: Bearer header was sent. `revoked_credentials` — The presented key was revoked. Create a new key in Settings → API.
- `403`: `feature_unavailable` — The tenant's tier does not currently include API access. Feature rollout flags cannot grant this entitlement. `permission_denied` — The key's permission does not allow this operation (readonly keys cannot call admin-only operations).
- `404`: `not_found` — No such resource in YOUR tenant. Ids belonging to another tenant are indistinguishable from missing ones.
- `409`: `conflict` — State conflict — e.g. live payment links already cover the installment, or a concurrent identical request is in flight.
- `413`: `payload_too_large` — The request body exceeds the 64 KiB limit.
- `429`: `rate_limit_exceeded` — Too many requests. Honor the Retry-After header (seconds) before retrying — waiting that long is enough. The RateLimit-* fields on every response say how much headroom is left before this happens; pace against them instead of retrying into a refusal.
- `500`: `internal_error` — Unexpected server error. Safe to retry with the same Idempotency-Key.

---

[API](https://skmtc.dev/getfinero/apis/finero-public-api.md) · [All operations](https://skmtc.dev/getfinero/apis/finero-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/getfinero/apis/finero-public-api/revisions/3d456e222775?raw)
