Skip to content
Merxian

Integration guides

Build a transaction

A transaction holds what the buyer pays for. Build it as a draft, finalize it to freeze the amounts, then collect it with a checkout session.

On this page

When to build the transaction yourself#

A checkout session can create the transaction for you from transactionDraft. Build the transaction yourself when you want to:

  • Show the final amount and the tax before the buyer goes to checkout.
  • Attach a stored customer or a billing address.
  • Apply a promotion code.
  • Keep your own reference and metadata on the transaction.

You need an API key with transactions:write and transactions:read. See Transactions for the model.

Create a draft#

Send either lines or amount, not both.

  • lines: each line names a catalogPriceId and a quantity. Merxian takes the name, the unit amount, and the tax code from the catalog. You cannot send your own description or unit amount.
  • amount: one gross amount in minor units, with no lines. An account on which Merxian calculates tax cannot use amount. Such a request returns 422 with the code amount_only_not_allowed.
Create a transaction
curl -X POST https://api.merxian.com/v1/transactions \
  -H "Authorization: Bearer $MERXIAN_API_KEY" \
  -H "Idempotency-Key: 9b3f6c1e-2a47-4d8b-b5e0-7c1d2e3f4a5b" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "EUR",
    "lines": [{ "catalogPriceId": "price_4Wm9TqLz2Xb7KdN8r", "quantity": 1 }],
    "customerId": "cus_2Lp7XcN4vB8mQ1tKd",
    "billingAddress": {
      "line1": "Torstraße 1",
      "city": "Berlin",
      "postalCode": "10119",
      "country": "DE"
    },
    "externalReference": "A-1042",
    "metadata": { "order_ref": "A-1042" }
  }'

The response is a transaction with status: "draft" and revision: 1. amounts holds subtotal, discount, net, tax, and total in minor units. A total of 14280 in EUR is €142.80. See POST/v1/transactions.

The buyer fields#

Field Use it for
customerId A stored customer of your account, cus_….
buyer Buyer details for this transaction only: email, name, country, customerType, vatId, phone. Values in buyer override the stored customer values.
billingAddress The billing address: line1, city, postalCode, and country are required.
promotionCode A promotion code of your account. It needs lines.
externalReference Your own reference, for example a reference number from your own system.
metadata Your own key-value pairs. At most 50 entries, keys up to 64 characters, values up to 1024 characters.

Preview the amounts#

POST/v1/transactions/preview takes the same body as create. It returns the transaction that the request would create, with its tax and discounts, and stores nothing. It needs only transactions:read and no Idempotency-Key. Use it to show a price summary before you create the transaction.

Update a draft#

PATCH/v1/transactions/{transactionId} replaces the commercial content of a draft. Send the full content again, not only the changed fields.

To prevent lost updates, send the revision that you last read. Use the If-Match header with the weak form W/"<revision>", or the expectedRevision field.

Update a draft
curl -X PATCH https://api.merxian.com/v1/transactions/txn_0F8mQ2rXbT4kL9pZa \
  -H "Authorization: Bearer $MERXIAN_API_KEY" \
  -H 'If-Match: W/"1"' \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "EUR",
    "lines": [{ "catalogPriceId": "price_4Wm9TqLz2Xb7KdN8r", "quantity": 2 }],
    "customerId": "cus_2Lp7XcN4vB8mQ1tKd"
  }'

If the transaction changed after that revision, the request returns 409 with the code revision_conflict. Read the transaction again, apply your change to the new content, and send the update with the new revision.

You cannot change a draft from lines to amount, or from amount to lines. Create a new transaction instead.

Finalize#

POST/v1/transactions/{transactionId}/finalize moves the transaction from draft to ready. Merxian calculates the final amounts, discounts, and tax, and freezes them with the buyer and line details.

Finalize a transaction
curl -X POST https://api.merxian.com/v1/transactions/txn_0F8mQ2rXbT4kL9pZa/finalize \
  -H "Authorization: Bearer $MERXIAN_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Finalize can return 422 with the code invalid_transaction when the draft is not complete. For example:

  • When Merxian calculates tax, it needs the buyer country. Send buyer.country, a customer with a country, or a billingAddress.
  • When Merxian issues the invoice, the transaction needs a buyer and a billing address.
  • All lines must use the currency of the transaction. Otherwise the code is currency_mismatch.

Read message, complete the draft with an update, and finalize again. You receive transaction.ready after a successful finalize.

Collect the transaction#

Create a checkout session with the transactionId. The session can take a draft or a ready transaction.

Create a checkout session for the transaction
curl -X POST https://api.merxian.com/v1/checkout-sessions \
  -H "Authorization: Bearer $MERXIAN_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "transactionId": "txn_0F8mQ2rXbT4kL9pZa",
    "successUrl": "https://shop.example.com/checkout/success",
    "cancelUrl": "https://shop.example.com/checkout/cancel",
    "clientReferenceId": "A-1042"
  }'

Continue with Accept a payment with hosted checkout.

Try refund, payment.succeeded,POST /v1/transactions, orIdempotency-Key.