Procare Pay Integration Service

Complete API Documentation for Payment Processing

Process Transaction Sale

POST /v1/rest/merchants/{merchantId}/transactions

Description: Processes a new payment transaction (sale). This endpoint charges a credit card or ACH account immediately. You can use either a saved payment method (by providing the payor and payment method IDs) or provide new payment information.

What is this endpoint used for?

This is how you charge a customer for a purchase. Think of it like swiping a credit card or processing a check payment:

  • E-commerce: Customer checks out and pays online
  • Recurring billing: Charge a saved payment method automatically
  • Phone orders: Process credit card over the phone
  • Invoicing: Charge a customer's saved payment method for an invoice
Important: This endpoint processes real financial transactions that result in actual money movement. Ensure you have proper authorization from the customer and are handling sensitive payment data securely. Test thoroughly in a sandbox environment before using in production.
Important Note: It is strongly recommended that integrators use the Procare Pay Hosted Payments Page to process one-time payments. This API is intended for advanced use cases where direct API integration is necessary. Using the hosted page ensures PCI compliance and reduces the scope of sensitive data handling. Calling this endpoint for one-time payments (payments that require account information to be transmitted) directly from your integrated application will include your application in PCI scope!

Path Parameters

merchantId (required)
Type: string
Description: The merchant identifier

Request Body Fields

Field Type Required Description
amount object Required The transaction amount (contains dollars and/or cents)
payorId string Optional* The payor ID (use with savedPaymentMethodId for saved payment methods)
savedPaymentMethodId string Optional* The saved payment method ID (use with payorId)
encryptedAccountNumber string Optional* Encrypted account number (credit card or bank account) - required if not using saved payment method
cardExpiry string Optional Card expiration in MMyy, MMyyyy, or yyyyMMdd format (required for credit cards)
abaRoutingNumber string Optional Bank routing number (required for ACH)
encryptedCvv2 string Optional Encrypted CVV2/security code (recommended for credit cards)
accountHolderName string Required Name on the account
address string Optional Billing street address
city string Optional Billing city
postal string Optional Billing ZIP/postal code
region string Optional State/province (required for ACH)
phone string Optional Account holder phone number
email string Optional Account holder email address
orderid string Optional Your system's order number (for tracking)
locationid integer Optional Location/school ID
bankAccountType string Optional Account type: Checking, Saving, CreditCard, or Null
transtype string Optional Transaction type: Ecomm (default), Moto, or Retail
transinit string Optional Transaction initiator: Consumer (default) or Merchant
recurring boolean Optional Indicates recurring/installment payment (default: false)
allowPartialApproval boolean Optional Allow partial authorization (default: true)
savePaymentMethod boolean Optional Save payment method for future use (default: false)
customAttributes object Optional Custom key-value pairs for tracking
*Payment Method Options:

You must provide payment information in ONE of these ways:

  • Option 1: Saved payment method: Provide both payorId and savedPaymentMethodId
  • Option 2: New payment method: Provide encryptedAccountNumber (plus cardExpiry for cards or abaRoutingNumber for ACH)

Authentication

This endpoint requires bearer token authentication using the Authorization header.

Note: The bearer token must be a valid Cognito token.

Code Examples

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using Newtonsoft.Json;

public class TransactionRequest
{
    [JsonProperty("amount")]
    public AmountRequest Amount { get; set; }

    [JsonProperty("payorId")]
    public string PayorId { get; set; }

    [JsonProperty("savedPaymentMethodId")]
    public string SavedPaymentMethodId { get; set; }

    [JsonProperty("encryptedAccountNumber")]
    public string EncryptedAccountNumber { get; set; }

    [JsonProperty("cardExpiry")]
    public string CardExpiry { get; set; }

    [JsonProperty("encryptedCvv2")]
    public string EncryptedCvv2 { get; set; }

    [JsonProperty("accountHolderName")]
    public string AccountHolderName { get; set; }

    [JsonProperty("address")]
    public string Address { get; set; }

    [JsonProperty("city")]
    public string City { get; set; }

    [JsonProperty("postal")]
    public string Postal { get; set; }

    [JsonProperty("region")]
    public string Region { get; set; }

    [JsonProperty("phone")]
    public string Phone { get; set; }

    [JsonProperty("email")]
    public string Email { get; set; }

    [JsonProperty("orderid")]
    public string OrderId { get; set; }

    [JsonProperty("locationid")]
    public int? LocationId { get; set; }

    [JsonProperty("transtype")]
    public string TransType { get; set; }

    [JsonProperty("recurring")]
    public bool Recurring { get; set; }

    [JsonProperty("savePaymentMethod")]
    public bool SavePaymentMethod { get; set; }

    [JsonProperty("customAttributes")]
    public Dictionary<string, string> CustomAttributes { get; set; }
}

public class AmountRequest
{
    [JsonProperty("dollars")]
    public decimal? Dollars { get; set; }

    [JsonProperty("cents")]
    public decimal? Cents { get; set; }
}

public class TransactionClient
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl = "https://your-api-domain.com";
    private readonly string _bearerToken;

    public TransactionClient(string bearerToken)
    {
        _bearerToken = bearerToken;
        _httpClient = new HttpClient();
        _httpClient.BaseAddress = new Uri(_baseUrl);
        _httpClient.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", _bearerToken);
        _httpClient.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
    }

    public async Task<string> ProcessTransactionAsync(
        string merchantId,
        TransactionRequest request)
    {
        try
        {
            string endpoint = $"/v1/rest/merchants/{merchantId}/transactions";

            string jsonContent = JsonConvert.SerializeObject(
                request,
                new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore
                });

            var content = new StringContent(
                jsonContent,
                Encoding.UTF8,
                "application/json");

            HttpResponseMessage response = await _httpClient.PostAsync(endpoint, content);
            response.EnsureSuccessStatusCode();

            return await response.Content.ReadAsStringAsync();
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"Request error: {e.Message}");
            throw;
        }
    }
}

// Example 1: Process transaction with saved payment method
var client = new TransactionClient("your-bearer-token-here");
var request = new TransactionRequest
{
    Amount = new AmountRequest { Dollars = 150.00m },
    PayorId = "5513027774438108364",
    SavedPaymentMethodId = "5513027774438108365",
    AccountHolderName = "John Doe",
    OrderId = "ORD-2026-12345",
    LocationId = 5,
    TransType = "Ecomm",
    Recurring = false,
    CustomAttributes = new Dictionary<string, string>
    {
        { "invoiceNumber", "INV-001" },
        { "department", "Sales" }
    }
};

string result = await client.ProcessTransactionAsync("12345678901", request);
Console.WriteLine(result);
Imports System
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Text
Imports System.Threading.Tasks
Imports System.Collections.Generic
Imports Newtonsoft.Json

Public Class TransactionRequest
    <JsonProperty("amount")>
    Public Property Amount As AmountRequest

    <JsonProperty("payorId")>
    Public Property PayorId As String

    <JsonProperty("savedPaymentMethodId")>
    Public Property SavedPaymentMethodId As String

    <JsonProperty("accountHolderName")>
    Public Property AccountHolderName As String

    <JsonProperty("orderid")>
    Public Property OrderId As String

    <JsonProperty("locationid")>
    Public Property LocationId As Integer?

    <JsonProperty("transtype")>
    Public Property TransType As String

    <JsonProperty("recurring")>
    Public Property Recurring As Boolean

    <JsonProperty("customAttributes")>
    Public Property CustomAttributes As Dictionary(Of String, String)
End Class

Public Class AmountRequest
    <JsonProperty("dollars")>
    Public Property Dollars As Decimal?

    <JsonProperty("cents")>
    Public Property Cents As Decimal?
End Class

Public Class TransactionClient
    Private ReadOnly _httpClient As HttpClient
    Private ReadOnly _baseUrl As String = "https://your-api-domain.com"
    Private ReadOnly _bearerToken As String

    Public Sub New(bearerToken As String)
        _bearerToken = bearerToken
        _httpClient = New HttpClient()
        _httpClient.BaseAddress = New Uri(_baseUrl)
        _httpClient.DefaultRequestHeaders.Authorization =
            New AuthenticationHeaderValue("Bearer", _bearerToken)
        _httpClient.DefaultRequestHeaders.Accept.Add(
            New MediaTypeWithQualityHeaderValue("application/json"))
    End Sub

    Public Async Function ProcessTransactionAsync(
        merchantId As String,
        request As TransactionRequest) As Task(Of String)

        Try
            Dim endpoint As String = $"/v1/rest/merchants/{merchantId}/transactions"

            Dim jsonContent As String = JsonConvert.SerializeObject(
                request,
                New JsonSerializerSettings With {
                    .NullValueHandling = NullValueHandling.Ignore
                })

            Dim content As New StringContent(
                jsonContent,
                Encoding.UTF8,
                "application/json")

            Dim response As HttpResponseMessage = Await _httpClient.PostAsync(endpoint, content)
            response.EnsureSuccessStatusCode()

            Return Await response.Content.ReadAsStringAsync()
        Catch e As HttpRequestException
            Console.WriteLine($"Request error: {e.Message}")
            Throw
        End Try
    End Function
End Class

' Example: Process transaction with saved payment method
Dim client As New TransactionClient("your-bearer-token-here")
Dim request As New TransactionRequest With {
    .Amount = New AmountRequest With {.Dollars = 150D},
    .PayorId = "5513027774438108364",
    .SavedPaymentMethodId = "5513027774438108365",
    .AccountHolderName = "John Doe",
    .OrderId = "ORD-2026-12345",
    .LocationId = 5,
    .TransType = "Ecomm",
    .Recurring = False
}

Dim result As String = Await client.ProcessTransactionAsync("12345678901", request)
Console.WriteLine(result)
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.Map;

class TransactionRequest {
    private AmountRequest amount;
    private String payorId;
    private String savedPaymentMethodId;
    private String accountHolderName;
    private String orderid;
    private Integer locationid;
    private String transtype;
    private Boolean recurring;
    private Map<String, String> customAttributes;

    // Getters and setters...
}

class AmountRequest {
    private Double dollars;
    private Double cents;

    public AmountRequest(Double dollars) {
        this.dollars = dollars;
    }
    // Getters and setters...
}

public class TransactionClient {
    private final String baseUrl;
    private final String bearerToken;
    private final HttpClient httpClient;
    private final Gson gson;

    public TransactionClient(String baseUrl, String bearerToken) {
        this.baseUrl = baseUrl;
        this.bearerToken = bearerToken;
        this.httpClient = HttpClient.newHttpClient();
        this.gson = new Gson();
    }

    public String processTransaction(String merchantId, TransactionRequest request)
            throws IOException, InterruptedException {

        String endpoint = baseUrl + "/v1/rest/merchants/" + merchantId + "/transactions";
        String jsonBody = gson.toJson(request);

        HttpRequest httpRequest = HttpRequest.newBuilder()
            .uri(URI.create(endpoint))
            .header("Authorization", "Bearer " + bearerToken)
            .header("Content-Type", "application/json")
            .header("Accept", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
            .build();

        HttpResponse<String> response = httpClient.send(
            httpRequest,
            HttpResponse.BodyHandlers.ofString()
        );

        if (response.statusCode() != 200) {
            throw new IOException("HTTP Error: " + response.statusCode());
        }

        return response.body();
    }
}

// Example: Process transaction with saved payment method
TransactionClient client = new TransactionClient(
    "https://your-api-domain.com",
    "your-bearer-token-here"
);

TransactionRequest request = new TransactionRequest();
request.setAmount(new AmountRequest(150.00));
request.setPayorId("5513027774438108364");
request.setSavedPaymentMethodId("5513027774438108365");
request.setAccountHolderName("John Doe");
request.setOrderid("ORD-2026-12345");
request.setLocationid(5);
request.setTranstype("Ecomm");
request.setRecurring(false);

String result = client.processTransaction("12345678901", request);
System.out.println(result);
require 'net/http'
require 'uri'
require 'json'

class TransactionClient
  def initialize(base_url, bearer_token)
    @base_url = base_url
    @bearer_token = bearer_token
  end

  def process_transaction(merchant_id, request_data)
    endpoint = "#{@base_url}/v1/rest/merchants/#{merchant_id}/transactions"
    uri = URI.parse(endpoint)

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true

    request = Net::HTTP::Post.new(uri.path)
    request['Authorization'] = "Bearer #{@bearer_token}"
    request['Content-Type'] = 'application/json'
    request['Accept'] = 'application/json'
    request.body = request_data.to_json

    response = http.request(request)

    if response.code.to_i != 200
      raise "HTTP Error: #{response.code} - #{response.body}"
    end

    response.body
  end
end

# Example: Process transaction with saved payment method
client = TransactionClient.new(
  'https://your-api-domain.com',
  'your-bearer-token-here'
)

request_data = {
  amount: {
    dollars: 150.00
  },
  payorId: '5513027774438108364',
  savedPaymentMethodId: '5513027774438108365',
  accountHolderName: 'John Doe',
  orderid: 'ORD-2026-12345',
  locationid: 5,
  transtype: 'Ecomm',
  recurring: false,
  customAttributes: {
    invoiceNumber: 'INV-001',
    department: 'Sales'
  }
}

result = client.process_transaction('12345678901', request_data)
puts result

Example Request Bodies

Example 1: Charge Saved Payment Method

{
  "amount": {
    "dollars": 150.00
  },
  "payorId": "5513027774438108364",
  "savedPaymentMethodId": "5513027774438108365",
  "accountHolderName": "John Doe",
  "orderid": "ORD-2026-12345",
  "locationid": 5,
  "transtype": "Ecomm",
  "recurring": false
}

Example 2: One-Time Credit Card Payment (New Card)

{
  "amount": {
    "dollars": 75.50
  },
  "encryptedAccountNumber": "encrypted-card-number-here",
  "cardExpiry": "1227",
  "encryptedCvv2": "encrypted-cvv-here",
  "accountHolderName": "Jane Smith",
  "address": "123 Main St",
  "city": "Springfield",
  "postal": "62701",
  "region": "IL",
  "email": "jane@example.com",
  "orderid": "ORD-2026-12346",
  "transtype": "Ecomm",
  "savePaymentMethod": false
}

Example 3: ACH Payment

{
  "amount": {
    "dollars": 250.00
  },
  "encryptedAccountNumber": "encrypted-account-number-here",
  "abaRoutingNumber": "123456789",
  "bankAccountType": "Checking",
  "accountHolderName": "Bob Johnson",
  "address": "456 Oak Ave",
  "city": "Chicago",
  "postal": "60601",
  "region": "IL",
  "phone": "555-1234",
  "email": "bob@example.com",
  "orderid": "ORD-2026-12347",
  "transtype": "Ecomm",
  "savePaymentMethod": true
}

Example 4: Recurring Payment

{
  "amount": {
    "dollars": 49.99
  },
  "payorId": "5513027774438108364",
  "savedPaymentMethodId": "5513027774438108365",
  "accountHolderName": "John Doe",
  "orderid": "SUBSCRIPTION-2026-001",
  "recurring": true,
  "transinit": "Merchant",
  "customAttributes": {
    "subscriptionId": "SUB-12345",
    "billingPeriod": "monthly"
  }
}

Response Format

Success Response (HTTP 200)

{
  "responseStatus": "TransactionApproved",
  "responseMessage": "Approved",
  "responseCode": "000",
  "responseReason": null,
  "responseResult": "success",
  "legacyResponseCode": "A",
  "correlationId": "abc123-def456-ghi789",
  "transactionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "retref": 123456789,
  "merchid": "12345678901",
  "locationid": 5,
  "transactionAmount": "150.00",
  "authAmount": "150.00",
  "accttype": "VISA",
  "maskedAccountNumber": "************1234",
  "lastfour": "1234",
  "cardExpiry": "1227",
  "payorId": "5513027774438108364",
  "savedPaymentMethodId": "5513027774438108365",
  "accountHolderName": "John Doe",
  "orderid": "ORD-2026-12345",
  "requestDate": "2026-04-02T10:30:00Z",
  "authDate": "2026-04-02T10:30:03Z",
  "settlementStatus": "Authorized",
  "transtype": "Ecomm",
  "transinit": "Consumer",
  "recurring": false,
  "customAttributes": {
    "invoiceNumber": "INV-001",
    "department": "Sales"
  }
}

Declined Response (HTTP 200 with declined status)

{
  "responseStatus": "TransactionDeclined",
  "responseMessage": "Insufficient Funds",
  "responseCode": "051",
  "responseReason": "The transaction was declined due to insufficient funds",
  "responseResult": "failure",
  "legacyResponseCode": "D",
  "correlationId": "xyz789-abc123-def456",
  "transactionId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "retref": 123456790,
  "merchid": "12345678901",
  "transactionAmount": "150.00",
  "authAmount": "0.00",
  "accttype": "VISA",
  "maskedAccountNumber": "************1234",
  "lastfour": "1234",
  "requestDate": "2026-04-02T10:31:00Z",
  "settlementStatus": "Declined"
}

HTTP Status Codes

Status Code Description
201 Success - Transaction processed (check responseStatus for approved/declined)
400 Bad Request - Validation error (missing required fields, invalid format)
401 Unauthorized - Invalid or expired bearer token
500 Internal Server Error - Server error processing transaction
Important: A 201 HTTP status does NOT mean the transaction was successful, only that the transaction did not fail validation, was submitted for processing, and a response was received from our aquirer. You must check the responseStatus field. A value of "TransactionApproved" indicates success, while "TransactionDeclined" indicates the payment was declined by the bank.

Understanding Response Status Values

Response Status Meaning Action Required
TransactionApproved Transaction successful Complete order, send confirmation
TransactionDeclined Payment declined by bank Ask customer to use different payment method
TransactionValidationError Invalid request data Fix validation issues and retry
Error System error occurred Check correlationId and contact support

Best Practices

1. Always Check responseStatus

if (response.ResponseStatus == "TransactionApproved")
{
    // Success - complete the order
    CompleteOrder(orderId);
}
else if (response.ResponseStatus == "TransactionDeclined")
{
    // Declined - show user-friendly message
    ShowMessage("Payment declined. Please try a different payment method.");
}

2. Store Transaction IDs

Always store both transactionId and retref in your database. You'll need these for refunds, voids, and customer service inquiries.

3. Use Order IDs for Tracking

Always provide an orderid that links the transaction to your order in your system. This makes reconciliation and customer service much easier.

4. Handle Partial Approvals

If allowPartialApproval is true and the authAmount is less than transactionAmount, the card was only approved for a partial amount.

5. Encrypt Sensitive Data

Card numbers and CVV must be encrypted using the public keys from the /keys endpoints before sending to the API. Never send plain text card numbers.

6. Save Payment Methods When Appropriate

Set savePaymentMethod: true for recurring customers to enable one-click checkout and automatic billing in the future.

Common Use Cases

1. E-commerce Checkout

Customer enters credit card at checkout and completes purchase

2. Recurring Subscription Billing

Automatically charge saved payment method on billing date

3. Invoice Payment

Customer pays invoice using saved payment method

4. Phone Order (MOTO)

Customer service rep processes credit card over phone

5. Auto-Pay for Services

Automatically charge customer's saved ACH account monthly

Troubleshooting

Issue: Getting "TransactionValidationError"
  • Verify amount object contains either dollars or cents
  • Check that accountHolderName is provided
  • Ensure cardExpiry is in correct format (MMyy, MMyyyy, or yyyyMMdd)
  • For ACH, verify region and abaRoutingNumber are provided
  • Check that either (payorId + savedPaymentMethodId) OR encryptedAccountNumber is provided
Issue: Getting "TransactionDeclined"
  • Check responseCode for specific decline reason
  • Common reasons: insufficient funds, expired card, incorrect CVV, card reported lost/stolen
  • Ask customer to contact their bank or try different payment method
  • Do not retry declined transactions repeatedly - this may trigger fraud alerts
Issue: Customer charged but order not completed
  • Store transactionId immediately after successful response
  • Implement idempotency - check if transaction already exists before processing
  • Use webhook notifications to handle async settlement updates
  • Have a reconciliation process to match transactions to orders

Security Considerations

  • PCI Compliance: Never store plain text card numbers in your system
  • Encryption: Always encrypt card numbers and CVV before sending to API
  • HTTPS Only: Always use HTTPS for all API requests
  • Tokenization: Use saved payment methods (tokens) instead of storing raw card data
  • CVV: Never store CVV/CVV2 codes - they should only be used for the initial transaction
  • Logging: Never log full card numbers - use masked numbers only
  • Rate Limiting: Implement rate limiting to prevent abuse

Additional Notes

  • Credit card transactions are authorized immediately and typically settle within 1-2 business days
  • ACH transactions take 3-5 business days to settle and can be reversed within 60 days
  • Set transtype to "Moto" for phone/mail orders to indicate card-not-present transaction
  • Set recurring: true for subscription payments to get better approval rates
  • The correlationId is essential for troubleshooting - always log it
  • Declined transactions still create a transaction record for tracking purposes
  • Partial approvals are more common with gift cards and prepaid cards