# Contracts Building with an AI agent? Start at https://docs.payme.io/agents.md How B2B payment contracts work: adding a card or direct-debit authorization to the payer's account, creating a contract and choosing its payment method, authentication, the contract lifecycle, callbacks and error codes. A payment contract moves money between two PayMe sellers on a set date. The seller that creates the contract is the **initiator**; the other seller is the **recipient**. The initiator either sends a payment (`payment.type` `1`) or requests one (`payment.type` `2`). PayMe asks the recipient to approve the contract by SMS or email, and runs the payment on `payment.due_date`. For the whole flow, from creating a contract to approval, payment and errors, see [Run a B2B payment contract end to end](/b2b-payments/contracts/contract-lifecycle). Amounts are in minor units (`1000` = 10.00). ## Payment methods The **payer** is the initiator on `payment.type` `1` and the recipient on `payment.type` `2`. | `payment.method` | Paid from | Limits | |---|---|---| | `funds-transfer` | The payer's PayMe balance | Don't send `buyer_key` (error `394`) | | `credit-card` | A card attached to the payer's seller account | Up to `5000000` (50,000.00) per contract (error `393`) | | `il-direct-debit` | An Israeli direct-debit authorization attached to the payer's seller account | `ILS` only (error `320`); up to `5000000` per contract (error `393`) | ## Before you start 1. The initiator needs a PayMe seller account and its `seller_payme_id` (MPL). Partners create one with [`create-seller`](/payments/merchants-management/post-create-seller). 2. For `credit-card` or `il-direct-debit`, add the payment method to the payer's seller account, as described below. 3. Create the contract with [`POST /payment-contracts`](/b2b-payments/contracts/post-user). ## Add a card or direct-debit authorization Tokenize the card or the bank account with [`generate-sale`](/payments/tokenization/post-generate-sale-tokenization) and `sale_type` `token`. The callback carries a `buyer_key` that identifies this payment method. Save it. ```http POST https://sandbox.payme.io/api/generate-sale Content-Type: application/json { "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567", "sale_price": 100, "currency": "ILS", "product_name": "Card for payment contracts", "sale_payment_method": "credit-card", "sale_type": "token", "sale_callback_url": "https://www.example.com/callback", "sale_return_url": "https://www.example.com/return" } ``` - For a direct-debit authorization, send `"sale_payment_method": "il-direct-debit"` instead. See [Israeli Direct Debit](/payments/il-direct-debit/post-generate-sale-il-direct-debit). - `sale_price` is required but not charged: PayMe sets it to `100` on a token request. - To prefill the payment page, add the buyer's details to the `sale_url` as query parameters: `first_name`, `last_name`, `phone`, `email` and `social_id`. For example: `https://sandbox.payme.io/sale/generate/SALE1700-000000AA-EXAMPLE1-SALE0001?first_name=Dana&last_name=Cohen&phone=0500000001&email=dana%40example.com`. ### Attach a card Attach the card's `buyer_key` to the payer's seller account with [`add-card-to-seller`](/payments/merchants-management/post-add-card-to-seller). Attached cards are listed in `seller_credit_cards` of [`get-sellers`](/payments/query-apis/post-get-sellers). ```http POST https://sandbox.payme.io/api/add-card-to-seller Content-Type: application/json { "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567", "buyer_key": "BUYERDEMO-BUYERDEMO-BUYERDEMO-1234567" } ``` ### Direct-debit authorizations attach themselves You don't attach a direct-debit authorization yourself. Once the bank approves it, usually after a few days, PayMe attaches it to the seller account. It then appears in `seller_bank_authorizations` of [`get-sellers`](/payments/query-apis/post-get-sellers) with `auth_status` `Active`. Until then it can't pay a contract (error `391`). ## Choose the payment method of a contract Send the payment method's `buyer_key` **at the top level** of the [`POST /payment-contracts`](/b2b-payments/contracts/post-user) body, not inside `payment`. `buyer_key` applies only to `credit-card` and `il-direct-debit`; it must belong to the payer's account (error `392`). If you don't send `buyer_key` on a contract that sends a payment (`payment.type` `1`), PayMe picks a payment method from the payer's account: - `credit-card`: among the attached cards that are still valid on `payment.due_date`, the card that **expires last**. If no attached card is valid on the due date, the call fails with error `390`. - `il-direct-debit`: the last authorization with `auth_status` `Active`. If there is none, the call fails with error `391`. ## Hosts and authentication Contracts use the Payments API hosts: `https://sandbox.payme.io/api` for testing and `https://live.payme.io/api` for production. Contract endpoints are under `/payment-contracts`. Every contract call identifies the seller by its `seller_payme_id` (MPL) in the `PayMe-Merchant-Key` header. On `POST /payment-contracts` you can send `seller_payme_id` in the JSON body instead; the file endpoints (`…/invoices`) read the header only. Partners can also send their client key in the `PayMe-Partner-Key` header. A call without a seller key fails with HTTP `500` and error `1`. See [Authentication](/payments/getting-started/authentication) for the keys themselves. To move funds between two sellers' balances right away, without a contract, use [Transfer funds between sellers](/b2b-payments/wallets/post-generate-transfer). ## Contract lifecycle | `status` | Meaning | |---|---| | `1` | Initial: waiting for the recipient to approve | | `2` | Recipient confirmed. PayMe confirms the initiator side at once, so the contract moves straight on to `3` | | `3` | Approved: waiting for the due date | | `4` | Completed: the payment ran | | `5` | Failed or cancelled: see `error_code` | - PayMe runs an approved contract once `payment.due_date` has passed. - A contract that isn't approved in time is cancelled automatically, with `error_code` `11002` or `11003`. - The initiator can cancel a contract with `PUT /payment-contracts/{guid}/cancellations`, sending the `PayMe-Merchant-Key` header and a JSON body such as `{"error_note": "Order cancelled"}`. The contract moves to status `5` with `error_code` `11001`. A completed or failed contract can't be cancelled (error `382`). - Retrying a create is safe: a request that repeats the initiator, recipient, `amount`, `currency`, `payment.due_date` and `payment.type` of a contract created in the last 5 minutes (and not failed) returns that contract instead of creating a second one. ## Callbacks If the contract has a `callback_url`, PayMe sends it a `POST` on every status change. The body is form-encoded (`application/x-www-form-urlencoded`, not JSON). It holds `notify_type` and every field of the contract, as in the [create response](/b2b-payments/contracts/post-user). | `notify_type` | When | |---|---| | `payment-contract-created` | The contract was created | | `payment-contract-recipient-approved` | The recipient approved | | `payment-contract-initiator-approved` | The initiator side was confirmed; the contract waits for the due date (status `3`) | | `payment-contract-recipient-rejected` | The recipient rejected the contract (`error_code` `11000`) | | `payment-contract-initiator-rejected` | The initiator side rejected the contract | | `payment-contract-canceled` | The initiator cancelled the contract (`error_code` `11001`) | | `payment-contract-confirmation-timeout` | The contract wasn't approved in time (`error_code` `11002` or `11003`) | | `payment-contract-payment-completed` | The payment ran (status `4`) | | `payment-contract-payment-failed` | The payment failed (`error_code` `11004`) | **Verify `payme_signature`.** Contracts use a shorter formula than [sale callbacks](/payments/getting-started/callbacks#verifying-a-callback-payme_signature): the lowercase hex MD5 of the partner's client key, the partner's client password and the contract `guid`, joined with no separator. The partner is the initiator's partner. A seller without a partner client key can't compute it: re-read the contract with `GET /payment-contracts/{guid}` (header `PayMe-Merchant-Key`) instead. ## Errors ### Contract `error_code` Values of `error_code` on a failed contract, with their `error_text`: | `error_code` | `error_text` | |--------------|--------------| | `11000` | Recipient Rejected | | `11001` | Initiator Canceled | | `11002` | Recipient Confirmation Timeout | | `11003` | Initiator Confirmation Timeout | | `11004` | Payment Processing Failure | This is the complete list. For `11004`, `error_note` is free text and may contain a regular PayMe error message. ### API error codes The contract endpoints return these codes in `status_error_code`: | Code | Message | When | |---|---|---| | `380` | Payment contract not found | No contract with this `guid` involves your seller account | | `381` | Not enough details for unique recipient identification | Only `recipient.business_code` was sent and it matches no PayMe seller. Add `email` or `phone` | | `382` | Cannot perform action due to payment contract status inconsistency | The action isn't allowed in the contract's current status | | `383` | Initiator and recipient are the same | The recipient is the initiator's own account | | `384` | Recipient account settings problem - please contact Customer Support | The recipient's seller account is inactive | | `385` | Action not allowed - please contact Customer Support | Your seller account isn't a side of this contract, or didn't upload this file | | `386` | Uploading multiple files not allowed - please contact Customer Support | Two files of the same `type`, or an unknown `type`, in one upload | | `387` | Uploading multiple files with same name not allowed | Two files with the same `name` in one upload | | `388` | File type has to be the same | A replacement file has a different `type` | | `389` | The payment method isn't attached to the payer's account, please attach it or use a different one | The payer has no attached card or direct-debit authorization | | `390` | The credit card expiration date is lower than the payment's due date, please add another payment method | No attached card is valid on `payment.due_date` | | `391` | We didn't find any bank debits we can use for that account, please create a new one or select a different payment method | No direct-debit authorization is `Active` | | `392` | The selected payment method isn't matching the provided token | `buyer_key` isn't one of the payer's attached payment methods | | `393` | The contract amount is over the maximum amount for the selected payment method | A `credit-card` or `il-direct-debit` contract over `5000000` | | `394` | The selected payment method does not match the provided token | `buyer_key` sent with `funds-transfer` | ## Guides - [Run a B2B payment contract end to end](/b2b-payments/contracts/contract-lifecycle): B2B contract flow. Header PayMe-Merchant-Key = MPL. payment.type 1 send (initiator pays) or 2 request (recipient pays); the recipient approves in PayMe. Methods: funds-transfer, credit-card, il-direct-debit (ILS only, 320); card/debit max 5000000 (393). Card: tokenize, add-card-to-seller, send buyer_key top level. A repeat create within 5 min returns the same contract. Status 1, 2, 3 (auto), 4; or 5 with error_code 11000-11004 (read error_code); payment-contract-* callbacks. Change: PUT /payment-contracts/{guid}; cancel: .../cancellations (initiator); files: .../invoices. Errors 380-394. ## Endpoints - [Create a payment contract](/b2b-payments/contracts/post-user): POST /payment-contracts - [List payment contracts](/b2b-payments/contracts/get-contracts): GET /payment-contracts - [List contract files](/b2b-payments/contracts/get-contracts-files): GET /payment-contracts/{payment_contract_guid}/invoices - [Upload contract files](/b2b-payments/contracts/post-contracts-files): POST /payment-contracts/{payment_contract_guid}/invoices - [Replace a contract file](/b2b-payments/contracts/put-contracts-files): PUT /payment-contracts/{payment_contract_guid}/invoices/{invoice_guid} - [Delete a contract file](/b2b-payments/contracts/delete-contracts-files): DELETE /payment-contracts/{payment_contract_guid}/invoices/{invoice_guid} - [List previous recipients](/b2b-payments/contracts/get-recipient): GET /payment-contracts/recipients