openapi: 3.1.0
info:
title: Embat AccountingAccounts Payments API
description: Embat API enables connections between any third party application and Embat. Is organized around REST principles, using HTTP responses code and returning data in JSON format. While testing the API, you have to request **sandbox credentials**.
contact:
name: API Support
url: https://embat.io/
email: tech@embat.io
version: 2.120.3
x-logo:
url: https://storage.googleapis.com/embat-production.appspot.com/assets/embat_dark.svg
tags:
- name: Payments
description: "`Payment` represents money moving between a bank transaction and the operations (invoices, bills) or accounting entries it settles. `customId` is the unique identifier of a payment: set your own value to use as your ERP payment ID, or let Embat auto-generate one.\n\nA payment links the bank world and the accounting world in Embat: it can represent the relationship between a `Transaction` (the bank movement) and one or more `Operations` (the invoices/bills being paid), a cash movement posted directly to an accounting account, or a movement involving a `Contact` (client or supplier). Payments can also reference a `Product` to resolve the accounting code used for classification, and a `Category` for reporting.\n\n**Typical flow:** payments synchronize accounting in both directions between your ERP and Embat.\n\n1. **Notify Embat of payments posted in your ERP.** When a payment is recorded in your ERP, create it in Embat with the operations it settles — each settled amount reduces the pending amount of the corresponding operation (invoice/bill) in Embat:\n\n```json\nPOST /payments/{companyId}\n{\n \"customId\": \"erp-payment-001\",\n \"date\": \"2024-01-15T00:00:00Z\",\n \"amount\": 1250.50,\n \"currency\": \"EUR\",\n \"operations\": [\n { \"customId\": \"invoice-2024-001\", \"amount\": 1250.50 }\n ]\n}\n```\n\n2. **Read payments created from Embat.** Periodically pull the payments generated in Embat that are pending on your side, using `GET /payments/{companyId}` with the `sync` filter (payments not yet synchronized) and `startUpdatedAt`/`endUpdatedAt` for incremental reads since your last poll. This endpoint never returns payments you created through `POST /payments/{companyId}` — retrieve those by `customId` with `GET /payments/{companyId}/{customId}`.\n3. **Confirm them back.** Once those payments are posted in your ERP, mark them as synchronized and registered (or record an `error`) with `PATCH /payments/{companyId}/{customId}` (or the bulk variant `PATCH /payments/{companyId}`).\n"
paths:
/payments/{companyId}:
get:
tags:
- Payments
summary: List payments
description: 'Returns the payments generated in Embat for a company. Payments you created through `POST /payments/{companyId}` are not included here — retrieve them by `customId` with `GET /payments/{companyId}/{customId}` instead. Results are paginated: use `limit` to control page size and pass the returned `nextPageToken` to fetch the next page. `startDate`/`endDate` filter by payment date, and `startUpdatedAt`/`endUpdatedAt` filter by last modification time, which is useful for incremental synchronization. `startDate`/`startUpdatedAt` are inclusive, `endDate`/`endUpdatedAt` are exclusive, and each date range spans at most 90 days. Payments missing required accounting, operation or contact information are excluded from the results.'
operationId: list_payments_payments__companyId__get
security:
- HTTPBearer: []
parameters:
- name: companyId
in: path
required: true
schema:
type: string
title: Companyid
- name: productId
in: query
required: false
schema:
type: string
description: Filter payments linked to a given product (`productId`).
title: Productid
description: Filter payments linked to a given product (`productId`).
- name: sync
in: query
required: false
schema:
type: boolean
description: Filter by synchronization status with the accounting system. `false` also matches payments where the value is not set.
title: Sync
description: Filter by synchronization status with the accounting system. `false` also matches payments where the value is not set.
- name: registered
in: query
required: false
schema:
type: boolean
description: Filter by registration status in the accounting system. `false` also matches payments where the value is not set.
title: Registered
description: Filter by registration status in the accounting system. `false` also matches payments where the value is not set.
- name: startDate
in: query
required: false
schema:
type: string
format: date
description: 'Only return payments dated on or after this date (inclusive). The range cannot exceed 90 days: if `endDate` is also given, the span between the two cannot exceed 90 days; if `endDate` is omitted, `startDate` cannot be more than 90 days in the past.'
title: Startdate
description: 'Only return payments dated on or after this date (inclusive). The range cannot exceed 90 days: if `endDate` is also given, the span between the two cannot exceed 90 days; if `endDate` is omitted, `startDate` cannot be more than 90 days in the past.'
- name: endDate
in: query
required: false
schema:
type: string
format: date
description: Only return payments dated before this date (exclusive). Combined with `startDate`, the range cannot exceed 90 days. If used without `startDate`, results start 90 days before this date.
title: Enddate
description: Only return payments dated before this date (exclusive). Combined with `startDate`, the range cannot exceed 90 days. If used without `startDate`, results start 90 days before this date.
- name: startUpdatedAt
in: query
required: false
schema:
type: string
format: date-time
description: 'Only return payments last modified on or after this timestamp (inclusive). The range cannot exceed 90 days: if `endUpdatedAt` is also given, the span between the two cannot exceed 90 days; if `endUpdatedAt` is omitted, `startUpdatedAt` cannot be more than 90 days in the past.'
title: Startupdatedat
description: 'Only return payments last modified on or after this timestamp (inclusive). The range cannot exceed 90 days: if `endUpdatedAt` is also given, the span between the two cannot exceed 90 days; if `endUpdatedAt` is omitted, `startUpdatedAt` cannot be more than 90 days in the past.'
- name: endUpdatedAt
in: query
required: false
schema:
type: string
format: date-time
description: Only return payments last modified before this timestamp (exclusive). Combined with `startUpdatedAt`, the range cannot exceed 90 days. If used without `startUpdatedAt`, results start 90 days before this timestamp.
title: Endupdatedat
description: Only return payments last modified before this timestamp (exclusive). Combined with `startUpdatedAt`, the range cannot exceed 90 days. If used without `startUpdatedAt`, results start 90 days before this timestamp.
- name: internalAttributes
in: query
required: false
schema:
type: boolean
description: Include attributes flagged as internal in the response.
default: false
title: Internalattributes
description: Include attributes flagged as internal in the response.
- name: limit
in: query
required: false
schema:
type: integer
maximum: 2000
title: Response length of objects limit
description: Maximum number of objects to return in the response. Default 500, maximum 2000.
default: 500
description: Maximum number of objects to return in the response. Default 500, maximum 2000.
- name: nextPageToken
in: query
required: false
schema:
type: string
title: Pagination token
description: Token to fetch the next page of results, taken from the `nextPageToken` returned by the previous request with the same filters. Omit it to fetch the first page. An invalid or malformed token is rejected with `404`.
description: Token to fetch the next page of results, taken from the `nextPageToken` returned by the previous request with the same filters. Omit it to fetch the first page. An invalid or malformed token is rejected with `404`.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ListPaymentsResponseSchema'
'400':
description: 'Invalid date range: when only a start bound (`startDate` or `startUpdatedAt`) is given, it must not be in the future and cannot be more than 90 days in the past.'
content:
application/json:
example:
detail: startDate is a date after endDate
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized. The bearer token is missing, invalid or expired.
content:
application/json:
example:
detail: user not authorized
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Company not found, invalid `nextPageToken`, or an invalid date range when both bounds are given (start after end, or a span of more than 90 days).
content:
application/json:
example:
detail: 0021 companyId not found
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
post:
tags:
- Payments
summary: Create payment
description: 'Creates a payment against one or more operations, recording that those operations (invoices/bills) have been settled in your ERP; each settled amount reduces the operation''s pending amount in Embat. If `customId` is omitted, Embat auto-generates one.
Each entry in `operations` is validated independently and **silently discarded** when: the referenced operation does not exist, the operation is already paid or canceled, a payment with the same `customId` was already notified for that operation (duplicates are ignored), or the operation already has payments created from Embat. Discarded entries produce no error: if only some operations are eligible the payment is created for those only, and if none are eligible the call still returns `200` with an `id` but **no payment is created**. When a payment covers an operation''s full amount, the operation is automatically marked as paid.'
operationId: create_payment_payments__companyId__post
security:
- HTTPBearer: []
parameters:
- name: companyId
in: path
required: true
schema:
type: string
title: Companyid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PostPaymentsRequestSchema'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModifyPaymentsResponseSchema'
'401':
description: Unauthorized. The bearer token is missing, invalid or expired.
content:
application/json:
example:
detail: user not authorized
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The requested resource or `companyId` does not exist.
content:
application/json:
example:
detail: 0021 companyId not found
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Unexpected error. Contact support if it persists.
content:
application/json:
example:
detail: Internal server error
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
patch:
tags:
- Payments
summary: Update payments in bulk
description: Updates the synchronization status, error message, registration status or additional info of several payments, identified by `customId`. Entries whose `customId` does not match any payment are silently skipped — the call returns `200` for the whole batch.
operationId: update_payments_bulk_payments__companyId__patch
security:
- HTTPBearer: []
parameters:
- name: companyId
in: path
required: true
schema:
type: string
title: Companyid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BulkPatchPaymentsRequestSchema'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/BulkModifyPaymentsResponseSchema'
'401':
description: Unauthorized. The bearer token is missing, invalid or expired.
content:
application/json:
example:
detail: user not authorized
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The requested resource or `companyId` does not exist.
content:
application/json:
example:
detail: 0021 companyId not found
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Unexpected error. Contact support if it persists.
content:
application/json:
example:
detail: Internal server error
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
delete:
tags:
- Payments
summary: Delete payments in bulk
description: Deletes several payments in a single call, identified by `customId`.
operationId: delete_payments_bulk_payments__companyId__delete
security:
- HTTPBearer: []
parameters:
- name: companyId
in: path
required: true
schema:
type: string
title: Companyid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BulkDeletePaymentsRequestSchema'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/BulkModifyPaymentsResponseSchema'
'401':
description: Unauthorized. The bearer token is missing, invalid or expired.
content:
application/json:
example:
detail: user not authorized
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Company not found, or none of the given `customId` values match a payment.
content:
application/json:
example:
detail: 0021 companyId not found
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Unexpected error. Contact support if it persists.
content:
application/json:
example:
detail: Internal server error
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/payments/{companyId}/{customId}:
get:
tags:
- Payments
summary: Retrieve payment
description: Returns a single payment by `customId`. Payments missing required accounting, operation or contact information are not returned even if they exist.
operationId: retrieve_payment_payments__companyId___customId__get
security:
- HTTPBearer: []
parameters:
- name: customId
in: path
required: true
schema:
type: string
title: Customid
- name: companyId
in: path
required: true
schema:
type: string
title: Companyid
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/GetPaymentsResponseSchema'
'401':
description: Unauthorized. The bearer token is missing, invalid or expired.
content:
application/json:
example:
detail: user not authorized
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Company not found, or no payment matches the given `customId`.
content:
application/json:
example:
detail: 0021 companyId not found
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
patch:
tags:
- Payments
summary: Update payment
description: Updates the synchronization status, error message, registration status or additional info of a payment identified by `customId`. If none of the provided fields change the existing payment, the update is a no-op. Note that updating a `customId` that does not match any payment also returns `200` without applying any change — no `404` is raised. Setting `error` without `sync` marks the payment as synchronized with the error recorded.
operationId: update_payment_payments__companyId___customId__patch
security:
- HTTPBearer: []
parameters:
- name: customId
in: path
required: true
schema:
type: string
title: Customid
- name: companyId
in: path
required: true
schema:
type: string
title: Companyid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchPaymentsRequestSchema'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModifyPaymentsResponseSchema'
'401':
description: Unauthorized. The bearer token is missing, invalid or expired.
content:
application/json:
example:
detail: user not authorized
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The requested resource or `companyId` does not exist.
content:
application/json:
example:
detail: 0021 companyId not found
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Unexpected error. Contact support if it persists.
content:
application/json:
example:
detail: Internal server error
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
delete:
tags:
- Payments
summary: Delete payment
description: Deletes a payment by `customId`.
operationId: delete_payment_payments__companyId___customId__delete
security:
- HTTPBearer: []
parameters:
- name: customId
in: path
required: true
schema:
type: string
title: Customid
- name: companyId
in: path
required: true
schema:
type: string
title: Companyid
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModifyPaymentsResponseSchema'
'401':
description: Unauthorized. The bearer token is missing, invalid or expired.
content:
application/json:
example:
detail: user not authorized
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Company not found, or no payment matches the given `customId`.
content:
application/json:
example:
detail: 0021 companyId not found
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Unexpected error. Contact support if it persists.
content:
application/json:
example:
detail: Internal server error
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/payments/{companyId}/bulk:
post:
tags:
- Payments
summary: Create payments in bulk
description: Creates several payments in a single call, following the same rules as the single payment creation endpoint. Payments sharing the same `customId` within the request are deduplicated and only the first occurrence is processed.
operationId: create_payments_bulk_payments__companyId__bulk_post
security:
- HTTPBearer: []
parameters:
- name: companyId
in: path
required: true
schema:
type: string
title: Companyid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BulkPostPaymentsRequestSchema'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/BulkUpsertPaymentsResponseSchema'
'401':
description: Unauthorized. The bearer token is missing, invalid or expired.
content:
application/json:
example:
detail: user not authorized
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not found. The requested resource or `companyId` does not exist.
content:
application/json:
example:
detail: 0021 companyId not found
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Unexpected error. Contact support if it persists.
content:
application/json:
example:
detail: Internal server error
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
ContactTypeEnum:
type: string
enum:
- supplier
- client-supplier
- client
title: ContactTypeEnum
ContactContactTypeEnum:
type: string
enum:
- freelance
- company
title: ContactContactTypeEnum
CurrencyEnum:
type: string
enum:
- AED
- AFN
- ALL
- AMD
- ANG
- AOA
- ARS
- AUD
- AWG
- AZN
- BAM
- BBD
- BDT
- BGN
- BHD
- BIF
- BMD
- BND
- BOB
- BOV
- BRL
- BSD
- BTC
- BTN
- BWP
- BYN
- BZD
- CAD
- CDF
- CHE
- CHF
- CHW
- CLF
- CLP
- CNH
- CNY
- COP
- COU
- CRC
- CUP
- CVE
- CZK
- DJF
- DKK
- DOP
- DZD
- EEK
- EGP
- ERN
- ETB
- ETH
- EUR
- FJD
- FKP
- GBP
- GEL
- GHS
- GIP
- GMD
- GNF
- GTQ
- GYD
- HKD
- HNL
- HRK
- HTG
- HUF
- IDR
- ILS
- INR
- IQD
- IRR
- ISK
- JMD
- JOD
- JPY
- KES
- KGS
- KHR
- KMF
- KPW
- KRW
- KWD
- KYD
- KZT
- LAK
- LBP
- LKR
- LRD
- LSL
- LTC
- LTL
- LVL
- LYD
- MAD
- MDL
- MGA
- MKD
- MMK
- MNT
- MOP
- MRU
- MUR
- MVR
- MWK
- MXN
- MXV
- MYR
- MZN
- NAD
- NGN
- NIO
- NOK
- NPR
- NZD
- OMR
- PAB
- PEN
- PGK
- PHP
- PKR
- PLN
- PYG
- QAR
- RON
- RSD
- RUB
- RWF
- SAR
- SBD
- SCR
- SDG
- SEK
- SGD
- SHP
- SLE
- SOS
- SRD
- SSP
- STN
- SVC
- SYP
- SZL
- THB
- TJS
- TMT
- TND
- TOP
- TRY
- TTD
- TWD
- TZS
- UAH
- UGX
- USD
- USN
- UYI
- UYU
- UYW
- UZS
- VED
- VEF
- VES
- VND
- VUV
- WST
- XAF
- XAG
- XAU
- XBA
- XBB
- XBC
- XBD
- XCD
- XDR
- XOF
- XPD
- XPF
- XPT
- XSU
- XTS
- XUA
- XXX
- YER
- ZAR
- ZMK
- ZMW
- ZWG
- ZWL
title: CurrencyEnum
ContactNewAccount:
properties:
default:
type: boolean
title: Default
description: Marks this account as the default one for its `currency`.
default: false
currency:
anyOf:
- $ref: '#/components/schemas/CurrencyEnum'
- type: 'null'
description: ISO currency code this account is used for. An empty string is treated the same as omitting this field.
examples:
- EUR
details:
anyOf:
- $ref: '#/components/schemas/ContactNewAccountDetails'
- type: 'null'
description: 'Bank account identifiers. Which fields are required depends on the `currency` and the destination country: IBAN-based currencies expect `iban`, others expect `accountNumber` plus the identifiers of the applicable payment rail (e.g. `routingNumber` for US accounts, `sortCode` for UK accounts).'
type: object
title: ContactNewAccount
BaseContactSchema-Output:
properties:
tradeName:
anyOf:
- type: string
- type: 'null'
title: Tradename
description: Commercial/trade name of the contact. Defaults to `legalName` when omitted or blank.
examples:
- Acme Supplies
legalName:
anyOf:
- type: string
- type: 'null'
title: Legalname
description: Legal (registered) name of the contact.
examples:
- Acme Supplies S.L.
taxId:
anyOf:
- type: string
- type: 'null'
title: Taxid
description: Tax identification number (CIF/NIF/VAT) of the contact. Spaces are removed before storage.
examples:
- B12345678
contact:
anyOf:
- $ref: '#/components/schemas/app__schemas__contacts__ContactSchema'
- type: 'null'
description: Contact person details (name, phone, email) for this contact.
address:
anyOf:
- $ref: '#/components/schemas/ContactAddressSchema'
- type: 'null'
description: Postal address of the contact.
contactType:
$ref: '#/components/schemas/ContactContactTypeEnum'
description: Whether the contact is a `company` or a `freelance` individual. Defaults to `company`.
default: company
type:
anyOf:
- $ref: '#/components/schemas/ContactTypeEnum'
- type: 'null'
description: 'Commercial relationship with the contact: `client`, `supplier` or `client-supplier`.'
accounts:
anyOf:
- items:
$ref: '#/components/schemas/ContactAccounts'
type: array
- type: 'null'
title: Accounts
description: 'Bank accounts of the contact. When omitted (or empty) and `paymentsAccounts` is provided, Embat derives one entry per payment account automatically: the derived `iban` holds the payment identifier resolved for the account''s currency (an IBAN for IBAN-based currencies, otherwise the local account number), `swift` takes the account''s `bic`, and `default` its `default` flag.'
paymentsAccounts:
anyOf:
- items:
$ref: '#/components/schemas/ContactNewAccount'
type: array
- type: 'null'
title: Paymentsaccounts
description: Bank accounts of the contact, one per currency/payment rail, with the identifiers required to pay it (IBAN, account number, routing number...). Each entry is validated independently and **silently discarded** when it has no usable account identifier for its `currency` (neither `iban` nor `accountNumber` set); format validity of the identifiers themselves is not enforced. Entries that resolve to the same account identifier are deduplicated, keeping only the first one.
additionalInfo:
anyOf:
- additionalProperties: true
type: object
- type: 'null'
title: Additionalinfo
description: Free-form key/value metadata to attach to the contact.
accountingCode:
anyOf:
- type: string
- type: 'null'
title: Accountingcode
description: Accounting account code this contact is linked to.
examples:
- '4300001'
paymentMethod:
anyOf:
- type: string
- type: 'null'
title: Paymentmethod
description: Preferred payment method for this contact.
examples:
- bank-transaction
paymentTerms:
anyOf:
- type: integer
- type: 'null'
title: Paymentterms
description: Payment terms granted to the contact, in days.
examples:
- 30
attributes:
anyOf:
- items:
$ref: '#/components/schemas/AttributeValueRequestSchema'
type: array
- type: 'null'
title: Attributes
description: Custom attribute
# --- truncated at 32 KB (66 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/embat/refs/heads/main/openapi/embat-payments-api-openapi.yml