Managing transactions
Authorize transactions, and process recurring payments. An overview of the Transactions API.

Primer's Transaction API enables you to process and manage payments across all processors and payment methods, through a unified transaction lifecycle.
This guide assumes you have read our Quick start guide.
Transactions will go through a series of statuses when progressing from authorization to final settlement.
Status | Description |
---|---|
Pending | An authorization request has been received and submitted to the processor, but is yet to reach "Authorized" status. This typically occurs for asynchronous processors, such as Direct Debit providers. |
Authorized | The transaction has been authorized by the processor and can proceed to capture. This status occurs when performing authorization-only requests. Merchants will typically fulfil orders at this stage. |
Declined | This transaction was declined by the processor, either at a gateway or acquirer level. See the reason object in your response payload for more details. |
Settling | Funds have been captured and are due to be settled to your designated bank account for this processor and merchant ID. Merchants will typically fulfil orders at this stage. |
Cancelled | The transaction has been cancelled. Typically this involves us sending a "void" request to the processor. |
Partially Settled | Funds have been partially captured for this transaction and will soon be settled to your bank account. Not all processors support partial capture. |
Settled | Funds have been settled to your bank account. Typically, no further actions will be taken. |
For transaction lifecycle requests, Primer will respond with a 200
provided the request was successfully processed.
The response will contain the following attributes:
Attributes | Description |
---|---|
success | true indicates that your intended request was successful.e.g. if you sent a cancellation request and the transaction was successfully cancelled, this attribute would be set to true . |
reason | If the event has been unsuccessful, a payload describing the problem. |
transaction | The Transaction object, representing the current state of the transaction. This contains Primer's unique transaction ID which you will use for subsequent transaction lifecycle requests. |
An example transaction lifecycle response:
12345678910111213141516171819
{"success": false,"reason": {"decisionType": "APPLICATION_ERROR", // null if success equals true"declineReason": "...", // null if decisionType is not equal to ISSUER_DECLINED"message": "This request could not be honored because...""source": "BRAINTREE"},"transaction": {"createdAt": "2020-09-26T14:24:15.540899","id": "9483a0c5-b1c3-42f5-ab73-d3feee09fb46","primerAccountId": "2ff302dc-45d7-4759-85fc-cc905e7d3191","merchantId": "<YOUR_MERCHANT_ID>","processorTransactionId": "8ftnw094","orderId": "order-123","status": "DECLINED","riskData": [... // AVS, CVV and proprietary risk data],
If Primer responds with a 4XX
, there has been an API validation error, and the request has not been sent to the processor.
In this case, the response payload will contain an error
object with the following attributes:
Attributes | Description |
---|---|
errorId | The error code returned from Primer indicating the reason for rejection. |
description | A human readable description of the error. |
diagnosticsId | A unique identifier of the request. Please quote this identifier when contacting your account manager. |
validationErrors | A list of validation errors (if applicable). |
An example error response:
123456789101112131415161718
{"error": {"errorId": "RequestValidationError","description": "We were unable to validate your request, please check your payload against https://primer.io/docs/api","diagnosticsId": "11738938659721344025","validationErrors": [{"model": "BasicPaymentAPIRequest","errors": [{"path": "$.amount","description": "Missing required field"}]}]}}
Our Transactions API supports idempotency by providing an optional Idempotency-Key
header.
Multiple requests to the same endpoint using the same idempotency key will be processed only once.
For example, if we successfully receive a request but the connection drops before you receive a response, you may automatically retry that request. Without the use of an idempotency key, we would process the request a second time. By supplying an idempotency key, we ensure that the retried request is not processed a second time.
This example demonstrates a valid, authenticated, idempotent request.
1234567891011
curl --location --request \POST 'https://api.sandbox.primer.io/transactions/auth' \--header 'X-Api-Key: <YOUR_API_KEY>' \--header 'Idempotency-Key: order-123' \--data '{"paymentMethod": "<YOUR_TOKEN>","orderId": "order-123","amount": 700,"currencyCode": "EUR","merchantId": "<YOUR_MERCHANT_ID>"}'
Many payment methods support an auth and capture flow, where authorizing the transaction will put a hold on customer funds for a period of time (typically determined by the card scheme), and capturing will transfer funds from the customer's account to your acquirer - and bank account. Primer enables you to to perform authorization and capture requests separately, or at once.
Authorizing a payment
Primer sends an auth and capture request by default. If you want to authorize and capture separately then pass capture: false
on the authorization request.
Upon success, the transaction will transition to SETTLING
or SETTLED
(depending on the payment method type).
For authorization-only requests, the transaction will transition to AUTHORIZED
where it is ready for a capture or cancel request.
Parameters | Description |
---|---|
paymentMethod | A one-time use token generated from our checkout libraries, or a recurring token retrieved from the Vault API. e.g. hXIHB_WfR2-M6PM13JDmQnwxNjAxMTE3NTA4 . One-time use tokens expire after 15 minutes. |
orderId | Your reference for the transaction. |
amount | The amount you would like to charge the customer, in minor units. e.g. for $7, use 700 . |
currencyCode | The 3 digit currency code in ISO 4217 format. e.g. use USD for US dollars. |
merchantId | The unique merchant ID associated with your processor. Learn how to retrieve your merchant ID. |
vault | Vault options to store payment methods (if supported). Optional unless vaulting |
customerDetails | Details about your customer. e.g. shipping, billing address. Optional unless vaulting. |
capture | Whether or not the transaction should be directly submitted for settlement upon succesful authorization. true by default, or specify false for authorization-only requests. Optional |
An example auth/capture request:
1234567891011
curl --location --request \POST 'https://api.sandbox.primer.io/transactions/auth' \--header 'X-Api-Key: <YOUR_API_KEY>' \--header 'Idempotency-Key: order-123' \--data '{"paymentMethod": "<YOUR_TOKEN>", # one-time use, or recurring token"orderId": "order-123","amount": 700,"currencyCode": "EUR","merchantId": "<YOUR_MERCHANT_ID>"}'
Recurring payments
Primer enables you to store payment method information in our unified vault, for recurring transactions (when the payment method supports it). This agnostic storage layer enables you to process transactions across different processors (typically for card payments).
To store a payment method on authorization, set the vault
and customerDetails.customerId
attributes in your request.
This customerId
is your reference for the customer, and is used to subsequently retrieve payment methods for a given customer.
Vault Parameters | Description |
---|---|
paymentMethod | Set the value to ON_SUCCESS , this will vault your payment method if the authorization request was successful. |
recurring | Can be one of the following options:SCHEDULED subsequent recurring payments on a fixed schedule and a set amount, merchant-initiated (e.g subscriptions).SCHEDULED_FIRST the first in a series of recurring payments or subscription, customer-initiated. ONE_TIME unscheduled payments that are not recurring on a predefined schedule or amount, merchant-initiated (e.g. balance top-up). |
123456789101112131415161718
curl --location --request \POST 'https://api.sandbox.primer.io/transactions/auth' \--header 'X-Api-Key: <YOUR_API_KEY>' \--header 'Idempotency-Key: order-123' \--data '{"paymentMethod": "<YOUR_TOKEN>", # one-time use, or recurring token"orderId": "order-123","amount": 700,"currencyCode": "EUR","merchantId": "<YOUR_MERCHANT_ID>","vault": {"paymentMethod": "ON_SUCCESS","recurring": "SCHEDULED",},"customerDetails": {"customerId": "<YOUR_CUSTOMER_ID>"}}'
Capture
If you have performed an authorization-only request, you can now fully capture, or partially capture funds from the authorization (depending on whether your selected processor supports it).
The transaction will be updated to SETTLED
or SETTLING
(depending on the payment method type).
Parameters | Description |
---|---|
amount | The amount you would like to capture, in minor units. The authorized currency is assumed. e.g. for $7, use 700 . Optional if no amount is specified it defaults to the full amount. |
final | Indicates whether the capture request is the final capture request. Optional Defaults to true . |
12345678
curl --location --request \POST 'https://api.sandbox.primer.io/transactions/<primer-transaction-id>/capture' \--header 'X-Api-Key: <YOUR_API_KEY>' \--header 'Idempotency-Key: order-123' \--data '{"amount": 700,"final": true}'
Cancelling a payment
Provided the transaction has not reached SETTLED
, Primer will typically send a "void" request to the processor, thereby cancelling the transaction and releasing the hold on customer funds.
Upon success, the transaction will transition to CANCELLED
.
Example cancellation request:
1234
curl --location --request \POST 'https://api.sandbox.primer.io/transactions/<YOUR-TRANSACTION-ID>/cancel' \--header 'X-Api-Key: <YOUR_API_KEY>' \--header 'Idempotency-Key: order-123' \
Refunding payments
By default, this request will refund the full amount. Optionally, pass in a lesser amount for a partial refund.
Parameters | Description |
---|---|
amount | The amount you would like to refund the customer, in minor units. e.g. for $7, use 700 . Optional defaults to captured amount. |
orderId | Your reference for the transaction. Optional by default this will be set to the authorization orderId . |
12345678
curl --location --request \POST 'https://api.sandbox.primer.io/transactions/<YOUR-TRANSACTION-ID>/refund' \--header 'X-Api-Key: <YOUR_API_KEY>' \--header 'Idempotency-Key: order-123' \--data '{"orderId": "order-123""amount": 100 # supply this parameter for a partial refund, otherwise defaults to full amount}'