The object model
How a payment flows
Customers come first, then the Receivable that references them, then Payment observations. A repeatedPUT with identical content returns 200 and changes nothing; see Safe retries.
Core model
Three resources
- Customer: a person or business that owes the Client. Optional Contacts describe people and channels through which that Customer can be reached. A Receivable assigns each referenced Customer a role: primary, joint, or guarantor.
- Receivable: one independently identifiable posted obligation with liable Customers, due date, financial type, source revision and source reference. Loan and service-charge profiles supply distinct typed context. Ingestion never authorizes recovery.
- Payment observation: a record of a payment, refund, or reversal received outside PayPathIQ. Once accepted, it cannot be edited. It reports external payment evidence; it does not initiate a payment.
409 dependency_missing; PayPathIQ does not create it automatically or queue the request.
Mapping your terminology
These mappings explain the concepts, not additional supported fields or industry profiles. V1 accepts loan and service-charge profiles; B2B invoices remain a model design test, not a supported launch profile.
PayPathIQ coordinates related Receivables through the collection-lead Customer’s Workflow. Supplying a Receivable does not give your Integration control over Workflows, communications, Commitments, automation, or collection policy.
Ownership of supplied data
An Integration is the connection through which your source system supplies records for an approved Client and Portfolio. A Source representation is the set of facts your Integration supplies for one record. You can update those facts, but not staff-managed facts or data supplied by another Integration. Reads return your Integration’s representation, not the combined operational record.Updates
PUT creates or replaces the complete source-owned representation. Send it with Content-Type: application/json.
PATCH uses RFC 7396 JSON Merge Patch and requires Content-Type: application/merge-patch+json; any other media type returns 415 unsupported_media_type. Omitted fields remain unchanged. null removes a nullable field: a Customer’s sourceReference or middleNames, and a Receivable’s balanceBreakdown, creditUnion.arrearsAmount, creditUnion.contractualInstalment, creditUnion.defaultDate, or creditUnion.totalOutstandingAmount. contacts and the safety assertion collections cannot be null: send "contacts": [] to deactivate every Contact, and send "state": "cleared" to clear an assertion. An array in a patch replaces the whole array, except for safety assertions (see below). The complete result must still be valid. Payment observations are immutable and do not support PATCH.
Updating Contacts
Give every Contact a stableexternalContactId from your source system, unique within its Customer. It follows the same rules as other external IDs. PayPathIQ uses it to match Contacts when you send contacts again:
- A Contact with a new
externalContactIdis added. - A Contact you no longer send is deactivated. PayPathIQ keeps it, with its message and call history, but stops using it. Sending the same
externalContactIdagain reactivates it. isMainsets the Customer’s main Contact, andisCustomerSelfmarks the Contact who is the Customer themself.
contacts from a PUT, or leave it out of a PATCH, to keep the current Contacts. Send "contacts": [] to deactivate them all. In a PATCH, contacts replaces the whole collection, so send every Contact you want to keep.
Contacts created without an externalContactId cannot be changed later. Any change to them returns 409 contact_update_unsupported. Always send externalContactId, even if you do not plan to update Contacts yet.
The latest update wins
PayPathIQ staff can also correct Customer and Contact details. Whichever update is newest wins, whether it came from your Integration or from staff:- PayPathIQ applies only the values you changed since your last accepted request. If you send a Contact’s email unchanged, a newer correction made by staff stays. If you send a new email, it replaces the staff correction.
- The same rule applies to the Customer’s name and
sourceReference, toisMain, and toisCustomerSelf. Marking one of your Contacts as the Customer themself moves that flag from any other Contact, including one staff created. MovingisMainto one of your Contacts makes it the main Contact, and removingisMainclears the main Contact only while it is still yours. - Staff deactivating or reactivating a Contact is an update too. It stands until your Integration next removes that Contact or adds it back.
GET response always returns what you last sent, not the current value in PayPathIQ.
PayPathIQ never gives an API-supplied Contact permission to receive outreach on its own. If staff allowed outreach to a Contact, any change to its name, email, phone, address, or isCustomerSelf, or deactivating it, removes that permission until staff allow it again. Replaced details stay in the Contact’s history.
The current implementation supports create, read, replacement, and merge patch for Customers and Receivables; immutable Payment observations; and explicit Receivable lifecycle commands.
The resource URL and normalized payload digest make identical retries safe. A changed Customer or Receivable payload becomes the next accepted source representation, subject to the Contact rules above. A changed payload for an existing payment-observation ID returns 409 payment_observation_conflict.
Posted source balance
recoverableAmount is the posted source obligation balance. Both launch profiles accept EUR amounts with exactly two decimal places. Other balances and instalment amounts provide context. Recovery authority is separate from importing these figures. For example, a loan may have a total outstanding amount of EUR 4,000 with a separately identifiable EUR 1,250 obligation submitted to PayPathIQ. Neither figure grants recovery authority.
Pause, clear-pause, close, and reopen are explicit commands. They are not ordinary status patches, and they never resume PayPathIQ automation automatically. Closing a Receivable that is already closed returns 200 with its current representation.
Payment observations
The retained record-level Payment-observation operation requires matching Source and working balances and no unused working credit. If those positions differ, new Payments, refunds and reversals return409 financial_operation_required; exact accepted retries remain safe. Acknowledge confirmed hosted Payments through payment reconciliation; a difference otherwise stays until matching evidence or an authorized correction resolves it.
For a supported observation:
- A
paymentapplies its explicitallocationsfirst. Each allocation names a Receivable and an exact EUR amount; a Receivable may appear once, the total may not exceed the paymentamount, and an allocation larger than its Receivable’s balance returns409 allocation_exceeds_balancewith nothing saved. - Without
allocations, the connection’s Client-approved allocation rule may apply.sole_open_receivableapplies up to the balance of the paying Customer’s single open Receivable (identify the Customer withexternalCustomerId) and does nothing when there are none or several. With the default rulenone, or when the rule does not apply, the whole amount stays unapplied. PayPathIQ never assumes oldest-first. - Unapplied funds are kept as received money against the Client (and the paying Customer when known). They do not reduce any Receivable. The response reports
allocationBasis(explicit,ruleorunapplied), the resolvedallocationsand theunappliedAmount. - Only allocated amounts reduce a Receivable. A Receivable read reports
financialPosition: the SourcesourceAmount, theconfirmedUnreconciledAmountthat confirmed allocated payments have taken off the working balance but the Source has not acknowledged, and the safe collectionworkingAmount. - A
refundorreversalrecords an exact amount against the original payment named inrelatedExternalPaymentObservationId, and may be partial. Its optionalallocationsreturn amounts to the Receivables that payment was allocated to; the remainder ofamountis taken from the payment’s unapplied funds, and withoutallocationsthe whole amount is. Each allocation may carry aresultingRecoverableAmountguard that must equal the Receivable’s currentrecoverableAmountplus the allocation, otherwise409 balance_mismatch. Cumulative corrections cannot exceed the payment, any one allocation, or the unapplied remainder, and cannot target a Receivable the payment was not allocated to; these return409 payment_observation_conflict. The response reports the returnedallocationswith their resulting balances and theunappliedAmounttaken. - A correction updates the canonical payment, its allocations and each Receivable’s working balance in one transaction. The payment becomes
refundedorreversedonly when nothing remains correctable. A refund or reversal is evidence that money has been or will be returned through your own merchant or provider process; it never executes a transfer, and it is reported separately from credits and write-offs. - Money left unapplied is reported in the change feed as
customer.updatedfor the paying Customer, so a consumer can see funds that reduced no Receivable. A payment with noexternalCustomerIdcannot be attributed to a Customer and has no feed entry. - PayPathIQ removes a changed Receivable’s
balanceBreakdown, because the old breakdown no longer adds up. Send a new breakdown withPATCHif you track one. - The payment, its allocations, ledger effects and audit evidence commit atomically. Repeating the identical payload with the same ID returns
200and changes nothing, including under concurrent submission; a different payload for an existing ID returns409 payment_observation_conflict. - You can still record a Payment observation after a Receivable is closed. It corrects the closed Receivable’s
recoverableAmountand does not reopen it.
Advanced
These topics build on the core model. You do not need them for your first integration.Safety assertions
Safety assertions report facts that can restrict collection or contact. Each assertion has atype, a state of active or cleared, and an effectiveAt UTC timestamp. Each type may appear at most once in a collection. Unknown types are rejected with 422.
Customer assertions go in the Customer’s safetyAssertions:
Receivable assertions go in the Receivable’s
receivableSafetyAssertions:
Recording Payment observations is still allowed while an assertion is active.
Only an explicit
"state": "cleared" clears an assertion. Omission never clears one: leaving out the whole collection, or leaving a type out of a collection you send, keeps that type’s last state, and responses keep showing it. Clearing an assertion does not automatically resume collection.
Non-cash financial changes
Credit notes, adjustments and write-offs have separate immutable resources under the Client:credit-notes/{externalEventId}, adjustments/{externalEventId} and write-offs/{externalEventId}. Supply the matching type, exact positive EUR amount, opaque externalReceivableId, a newer sourceRevision, UTC effectiveAt, typed reason and non-sensitive sourceReference. An adjustment also declares direction as increase or decrease; credits and write-offs decrease the balance.
The server commits evidence, ledger effect and audit together. Repeat an identical event safely after a lost response. Changed content under an accepted identity is rejected, and a separate ordered correction preserves the original evidence. These resources do not create Payments, execute refunds or grant recovery authority.
Transaction-feed connections can use these event operations as source balance writers. Snapshot-only event balance writes are unavailable; snapshot-only connections send Source balance snapshots instead. A descriptive update preserves the current working collection balance, including confirmed funds absent from the source checkpoint. A non-cash event retains its full source amount even when its working collection effect is capped at zero. The unused reduction remains a credit against later increases, so reversing a credit cannot restore amounts already paid.
Source balance snapshots
PUT /v1/clients/{clientCode}/balance-snapshots/{externalSnapshotId} accepts ordered Source balances for up to 100 Receivables. It needs receivables:write; GET needs receivables:read. Each snapshot declares a strictly increasing sourcePosition, the UTC moment asOf it describes, and for every Receivable a sourceRevision and recoverableAmount. Omitting a Receivable changes nothing for it.
PayPathIQ rejects, rather than guesses at, unordered evidence. A position that is not higher than every accepted position, or an asOf earlier than the latest accepted one, returns 409 source_position_conflict. A revision below the accepted revision, or a different balance at the same revision, returns 409 source_revision_conflict. Reusing a snapshot ID with different content returns 409 financial_event_conflict. An identical retry returns 200 and changes nothing. Any rejected line rejects the whole snapshot.
The connection’s declared feed mode decides what a snapshot means:
- snapshot-only: a newer authoritative balance becomes the Source position. The change is recorded as a plain ledger adjustment. PayPathIQ never labels it a Payment, Credit note or write-off, and routine reconcilable updates need no manual approval.
- transaction: the snapshot is a checkpoint. Financial events already accepted are not applied again. If the balance agrees with the ledger at
asOf, the response outcome ischeckpoint. If not, both figures are kept and the Receivable is held withsource_balance_mismatch.
asOf. If a Payment was confirmed at or before asOf, PayPathIQ cannot tell whether the snapshot already includes it. It keeps both figures, never restores paid debt, holds affected recovery and Payment actions with pending_payment_overlap_unknown, and reports the outcome held.
Reads show financialPosition.sourcePosition and, while a difference is unresolved, financialPosition.uncertainty with its reason, since and the contradicting snapshotAmount. A later snapshot never clears an unexplained hold by itself: a transaction-mode mismatch clears when a later checkpoint matches the ledger, and an overlap hold stays until the Source acknowledges the Payment through a matched receipt line. The first snapshot accepted after that acknowledgement stops subtracting the acknowledged amount, so the Payment is never deducted twice, and clears the hold. A Payment that is only partly acknowledged keeps its unacknowledged remainder deducted. Supply acknowledgement evidence through payment reconciliation; the snapshot operation has no resolution step of its own.
Asynchronous batches
PUT /v1/clients/{clientCode}/batches/{externalBatchId} queues up to 100 records for asynchronous processing, for initial loads that would otherwise need a slow serial request loop. GET on the same URL returns progress. Both need the write scope of every kind of record in the batch: customers:write, receivables:write (also for balance snapshots), payment_observations:write and financial_corrections:write. Ordinary synchronous requests stay available for routine updates.
Each record is { recordId, kind, externalId, body, dependsOn? }. kind is customer, receivable, payment_observation, credit_note, adjustment, write_off or balance_snapshot. externalId and body are exactly the URL identifier and body of the matching synchronous operation, validated by the same strict schema. A batch is limited by the 256 KiB request size, 100 records, 10 dependencies per record, and 2 queued or running batches per connection (429 batch_limit_exceeded). Each batch counts as one request against the rate limit; the records it contains do not.
202 means the batch is durably queued. It does not mean any record was accepted. Records run in array order. Each runs through the same authorization, validation and canonical operation as its synchronous route, and your grant is checked again when each one runs, so a scope or key revoked after submission fails the remaining records instead of applying them. A key that expires or is revoked fails the records not yet applied with 401 invalid_api_key.
A record reports one of:
succeeded: the operation accepted it.httpStatusis201if it created the resource and200if it updated it or was an identical replay.failed: the operation refused it.httpStatusandproblem.typegive the exact reason, the same one a synchronous request would return.dependency_failed: not attempted, because a record named independsOndid not succeed.blockedBynames it. PayPathIQ never guesses a half-applied or substitute operation.pending: not finished yet.
status is queued or running while work is outstanding, then succeeded, partially_succeeded or failed. Temporary refusals, such as 429 or 503, are retried automatically with delay before a record is reported failed.
Retrying is safe. Resend the same PUT with an identical body to recover from a lost acknowledgement: it returns 200 with current progress and queues nothing. A different body under the same identifier returns 409 batch_conflict. If processing is interrupted, a later run resumes from the first unfinished record. Because every operation is identity- and digest-safe, a record whose result was not saved is applied as an identical replay, so no Payment or other financial effect is repeated. To correct a failed record, send it again in a new batch or through its synchronous route.
A batch never declares a complete book by itself. bookCompleteness is always not_declared: a failed, truncated or dependency-blocked batch cannot settle, remove or flag any Receivable it did not mention. Record bodies are removed from storage once each record is final; the identifiers and outcomes are retained.
Complete books and missing records
Leaving a Receivable out of an incremental feed, a batch or a balance snapshot changes nothing: no balance, status, Payment or hold. To tell PayPathIQ that the Source’s whole book has been sent, load it with batches and then declare it:PUT /v1/clients/{clientCode}/book-completions/{externalCompletionId} with { scope: "all_receivables", asOf, sourcePosition, batches: [externalBatchId, ...], expectedReceivableCount }. It needs receivables:write. GET on the same URL returns the declaration.
PayPathIQ completes the declaration only after verifying that every listed batch belongs to your connection and Client, has finished succeeded with every record accepted (including records that depended on others), and that the distinct Receivables those batches accepted equal expectedReceivableCount. asOf cannot be later than the earliest listed batch submission, and sourcePosition must exceed every accepted declaration. A failed, truncated, partly accepted, still running or dependency-blocked load returns 409 book_completion_unverified and changes nothing.
In a verified book, every open Receivable that existed before the earliest listed batch and is not in the book is flagged as missing and its recovery and Payment actions are held, the same hold used for unexplained balance differences. PayPathIQ does not treat the absence as payment, forgiveness, cancellation or deletion: the balance, status, Payments and history are untouched, evidence is still accepted for the held Receivable, and every other Receivable continues. Receivables created after the load started, and closed Receivables, are not judged.
A flag is visible on the Receivable: financialPosition.missingFromCompleteBook carries the declaration’s externalCompletionId and the time it was since flagged, and a receivable.updated entry is added to the change feed when a flag is raised and when it is cleared.
A flag is cleared only by evidence or an authorized source action: a later verified complete book that contains the Receivable, an authorized close of the Receivable, or an authorized non-cash correction that brings the Source balance to zero. Each clears only this missing-record restriction. A Dispute, complaint, pause, balance hold or any other protection on the same Receivable stays in force, and clearing a flag never resumes recovery by itself. A partial correction leaves the flag in place. The declaration response lists up to 100 flagged Receivables with held or resolved state, the resolution that cleared it, and the exact omittedReceivableCount.
Source freshness
An approved connection can declare a freshness limit: the longest age of accepted source evidence, based on its agreed delivery cadence, at which PayPathIQ still acts on its balances. PayPathIQ records the cadence it was approved from as the limit’sbasis. There is no universal limit; a connection without an approved limit reports not_configured and is never held for age.
Only a newly accepted Receivable write, Payment observation or financial correction counts as fresh evidence. Customer writes, lifecycle commands, exact retries of earlier requests and rejected requests, including a stale-revision conflict, do not refresh it. GET /v1/clients/{clientCode}/source-freshness (scope receivables:read) returns the state (fresh, stale or not_configured), the limitSeconds and basis, lastEvidenceAt, staleAt, and whether recovery and new payment initiation are held.
Freshness is checked when PayPathIQ attempts each recovery action or new payment initiation for your Receivables, not only when you read the status. While a connection is stale, those attempts are refused with the reason source_stale. Other connections, and Receivables that did not come from a stale connection, continue.
A stale connection still accepts your source updates and Payment observations, confirmed provider payment results and reconciliation evidence, so balances can become accurate again. Fresh evidence ends only the freshness hold. It never clears a Dispute, a source pause or restriction, a recovery-entry hold or any other protection, and it does not resume recovery by itself.
Recovery entry
Importing a Receivable, even one that is posted or overdue, never starts recovery, contact or a Workflow. Each connection declares one recovery entry mode. Withexplicit_instruction, you authorize recovery for a Receivable with PUT /v1/clients/{clientCode}/recovery-instructions/{externalInstructionId} (scope recovery_instructions:write, separate from receivables:write). An instruction is scoped to one Receivable and revisioned: the first revision is 1 and each change adds exactly 1. Repeating the same revision with identical content is a safe retry; the same revision with different content, or a skipped revision, returns source_revision_conflict. Send withdrawn to hold recovery again. Ordinary Receivable updates keep an instruction in force.
With approved_rules, PayPathIQ evaluates a rule the Client has approved for the connection, currently a minimum number of days past the due date for a Receivable with a positive balance. Instructions are rejected with recovery_mode_mismatch. The rule is evaluated when the policy is approved and whenever the Receivable is accepted, and a scheduled job re-evaluates it every minute, in bounded batches, so a Receivable becomes eligible as time passes without a new write.
In both modes authorization is only one condition. Current source restrictions and pauses, Disputes, other actors’ protections, source freshness and collection activation are checked again when each action is attempted, and none is cleared by an instruction or a rule. GET an instruction to see recoveryHeld and the closed categories of holds.
A Source restriction you clear stays your own: it never clears another actor’s protection. In explicit_instruction mode an authorized instruction becomes suspended when you raise a restriction, pause or Dispute on its Receivable or Customers, and PUT of authorized is refused with recovery_restriction_active while one is open. Clearing the restriction does not resume recovery: send a new revision. An approved_rules connection resumes only because the Client-approved rule still applies. Each accepted instruction and each suspension is recorded in PayPathIQ’s audit evidence and the change feed as a receivable.updated change.
Collection summaries
GET /v1/clients/{clientCode}/collection-summaries/{externalReceivableId} returns PayPathIQ’s working position for one Receivable, separate from the source representation you sent. GET .../collection-summaries lists them by externalReceivableId with a cursor and limit. Both need the collection_summaries:read scope, which is separate from intake, corrections, recovery and payment initiation.
A summary shows the financialPosition (source, working, confirmed-but-unacknowledged and receipt-acknowledged amounts), a reconciliation.status, the current recovery holds and payment initiation holds as closed categories, authorized promise-to-pay and Payment-plan summaries, and the status of recent collection actions. A commitment appears only when every Receivable it covers belongs to your connection. You can read commitments but never create or edit them here.
Summaries never include staff notes, protected data, message content or provider responses, and only Receivables placed by your own grant are visible. They are informational: reading one never starts, resumes or clears recovery, and each recovery or payment action checks every control again when it is attempted. A read does not count as fresh source evidence. Responses are no-store.
Payment reconciliation
When a hosted payment request ispaid, PayPathIQ holds one provider-confirmed Payment with its allocations. Your accounting system later posts that money as one or more receipt lines. PUT /v1/clients/{clientCode}/payment-reconciliations/{externalReconciliationId} (scope payment_observations:write) acknowledges the Payment against those lines: { externalPaymentRequestId, receiptLines: [{ externalReceiptLineId, externalReceivableId, amount }] }. GET on the same URL (scope payment_observations:read) returns the receipt lines and, for the whole Payment, each allocation with its matchedAmount and unmatchedAmount, the total unmatchedAmount and any unappliedAmount.
A line matches only through stable references: the Payment request, the Client, EUR and the Receivable. It matches when the Receivable is allocated in that Payment and the line fits inside the allocated amount no earlier line has acknowledged. Equal amounts or nearby dates never match on their own. Several lines and several reconciliations can acknowledge one Payment progressively; the unmatched remainder stays explicit until the Payment is fully accounted for.
Reconciliation never moves money. It does not create or reduce a Payment, and it never changes the working balance. Repeating a reconciliation with the identical body returns 200. Reusing the identity with different evidence, or reusing a receipt line identity in another reconciliation, returns financial_event_conflict and records nothing. Competing submissions are serialised so the matched total can never exceed the allocated amount. A request that has no confirmed Payment returns payment_not_confirmed.
A Receivable read separates the Source sourceAmount, the confirmedUnreconciledAmount still awaiting acknowledgement, the receiptAcknowledgedAmount and the workingAmount.
A line that does not fit (an unallocated Receivable, or more than the allocated amount remaining) is stored as held with both figures preserved, and the affected Receivables have recovery and new payment initiation held. The Receivable shows financialPosition.receiptDifference. Other Receivables, confirmed Payments and further reconciliation evidence continue to be accepted. PUT .../payment-reconciliations/{externalReconciliationId}/resolution (scope financial_corrections:write) clears the hold with { basis, reference }: matching_evidence is accepted only once matched lines account for the full allocated amount of every held Receivable, and authorized_correction records the Source’s reference to a Client-authorized correction. Otherwise it returns reconciliation_resolution_invalid. Resolution clears only this restriction and never resumes recovery by itself.
Automatic posting of receipts into your accounting system is not part of this operation: you report what your accounting system has posted.
Receipt delivery
Each connection declares one receipt delivery owner,partner or paypathiq, so two systems never post the same receipt. GET /v1/clients/{clientCode}/payment-requests/{externalPaymentRequestId}/receipt-delivery (scope payment_requests:read) returns the owner, the capability PayPathIQ can deliver today, every delivery attempt with its stable reference, and the accounting acknowledgement. Delivery and acknowledgement are separate facts: a vendor accepting a delivery, or a file being exported, leaves the acknowledgement pending until exact receipt lines arrive through payment reconciliation.
PUT on the same URL (scope payment_requests:write, empty body) asks PayPathIQ to deliver. A partner-owned connection returns receipt_delivery_owned_by_partner. PayPathIQ-owned delivery is currently disabled for every route: Blockman documents read endpoints only, no Blockman transaction CSV import format is verified, and the Xero connection is read-only. The operation returns receipt_delivery_route_unsupported and records nothing; the capability lists each unverified route with its missing proof. A rejected attempt may be retried with the same reference. An ambiguous outcome is never retried and returns receipt_delivery_outcome_ambiguous until exact receipt evidence acknowledges the Payment.
Partner-owned delivery
Every connection declares exactly one receipt delivery owner,partner or paypathiq. On a partner connection your middleware takes confirmed Payments to your accounting system. On a paypathiq connection every operation in this section and every payment reconciliation operation returns receipt_delivery_owner_mismatch and records nothing, so two systems can never post the same receipt.
GET /v1/clients/{clientCode}/payment-deliveries (scope payment_observations:read) lists the provider-confirmed Payments of your hosted Payment requests, optionally filtered by accountingAcceptance, and GET .../payment-deliveries/{externalPaymentRequestId} returns one. Each carries a stable paymentReference, a stable allocationReference and externalReceivableId for every allocation, any unappliedAmount, and the progressive accountingAcceptance: pending, partially_acknowledged, acknowledged or held.
Four things stay distinct. Retrieval is a read and records nothing. Delivery is what you report with PUT .../payment-deliveries/{externalPaymentRequestId}/attempts/{externalAttemptId} (scope payment_observations:write): { channel: "api" | "file_download", outcome: "downloaded" | "delivered" | "failed" }. Accounting acceptance exists only when the receipt lines your accounting system posted are acknowledged through a payment reconciliation. A download or a delivered attempt never moves accountingAcceptance, funds or balances. Repeating an attempt with the identical body returns 200; reusing the identity with different evidence returns 409 financial_event_conflict. If a reconciliation response is lost, repeat it with the same identities: it returns 200, and a receipt line can never be acknowledged twice.
A worked synthetic journey, the same for a loan (credit_union.v1) and a service charge (property_management.v1) connection: a payer pays hosted request PAYREQ_1 for two Receivables; list payment deliveries and see accountingAcceptance: "pending"; deliver the Payment to accounting and record an attempt with outcome: "delivered", which leaves acceptance pending; once accounting posts the receipt lines, send them in a payment reconciliation and read the delivery again to see acknowledged.
Hosted payment requests
A partner with the separatepayment_requests:write scope can ask PayPathIQ for a hosted payment page for one Customer and a fixed set of Receivables: PUT /v1/clients/{clientCode}/payment-requests/{externalPaymentRequestId}. The response carries a secret paymentUrl on the Client’s verified payment domain. Send it only to the paying Customer. The payer enters card details on that page with the Client’s own payment provider merchant, so card data never passes through this API and funds stay with the Client’s merchant account.
A request fixes what the page can collect. Each amount must equal the Receivable’s exact current working balance, so a caller can neither raise an amount nor redirect it to another Receivable. The request is refused with a typed problem, before any payment attempt exists, when an amount is stale (payment_request_stale), the Customer is not liable or a Receivable is not payable (payment_request_not_payable), the source feed is stale or a hold applies (payment_request_held), a payment is already in progress (payment_attempt_in_progress), or the Client’s merchant is not configured (payment_merchant_unconfigured). A request for a Receivable outside your Client and approved Portfolio fails as a missing dependency. Creating a request is not source evidence and does not make a stale feed fresh.
Reusing the identifier with the identical body returns 200 with a fresh link while the request is open; a different body returns payment_request_conflict. A new request for the same Customer replaces the earlier unpaid one.
The payer confirms a contact detail PayPathIQ holds for the Customer, then submits the page, which starts the attempt and repeats the balance checks. GET the request to follow status: open, payment_in_progress, under_review, paid, expired, replaced or cancelled. Only the payment provider’s verified confirmation sets paid and immediately reduces the allocated working balances, with accounting posting still pending. Returning from the hosted page, an unknown or failed outcome and a repeated provider event never do. Provider activation for each Client stays a separate platform decision.
Loan connections request loan Receivables and service-charge connections request service-charge demands, and the payer page labels each item by its financial type. A connection whose profile does not match its Client’s type receives payment_request_unsupported. Creating a request and each status change appear in the change feed as payment_request.created and payment_request.updated, visible with the payment_requests:read scope.