Contracts
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.
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
- The initiator needs a PayMe seller account and its
seller_payme_id(MPL). Partners create one withcreate-seller. - For
credit-cardoril-direct-debit, add the payment method to the payer's seller account, as described below. - Create the contract with
POST /payment-contracts.
Add a card or direct-debit authorization
Tokenize the card or the bank account with generate-sale and sale_type token. The callback carries a buyer_key that identifies this payment method. Save it.
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. sale_priceis required but not charged: PayMe sets it to100on a token request.- To prefill the payment page, add the buyer's details to the
sale_urlas query parameters:first_name,last_name,phone,emailandsocial_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. Attached cards are listed in seller_credit_cards of get-sellers.
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 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 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 onpayment.due_date, the card that expires last. If no attached card is valid on the due date, the call fails with error390.il-direct-debit: the last authorization withauth_statusActive. If there is none, the call fails with error391.
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 for the keys themselves.
To move funds between two sellers' balances right away, without a contract, use Transfer funds between sellers.
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_datehas passed. - A contract that isn't approved in time is cancelled automatically, with
error_code11002or11003. - The initiator can cancel a contract with
PUT /payment-contracts/{guid}/cancellations, sending thePayMe-Merchant-Keyheader and a JSON body such as{"error_note": "Order cancelled"}. The contract moves to status5witherror_code11001. A completed or failed contract can't be cancelled (error382). - Retrying a create is safe: a request that repeats the initiator, recipient,
amount,currency,payment.due_dateandpayment.typeof 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.
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: 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 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: POST /payment-contracts
- List payment contracts: GET /payment-contracts
- List contract files: GET /payment-contracts/{payment_contract_guid}/invoices
- Upload contract files: POST /payment-contracts/{payment_contract_guid}/invoices
- Replace a contract file: PUT /payment-contracts/{payment_contract_guid}/invoices/{invoice_guid}
- Delete a contract file: DELETE /payment-contracts/{payment_contract_guid}/invoices/{invoice_guid}
- List previous recipients: GET /payment-contracts/recipients