Procare Pay Integration Service

Complete API Documentation for Payment Processing

Understanding RESTful Web Services

What is a RESTful Web Service?

A RESTful web service (also called a REST API) is a way for computer programs to communicate with each other over the internet. Think of it like a restaurant:

The Restaurant Analogy:
  • You (the customer) = Your application
  • The menu = The API documentation (tells you what's available)
  • Your order = An API request
  • The waiter = The API (delivers your request to the kitchen)
  • The kitchen = The server/database
  • Your food = The API response (the data you requested)

Just like you tell the waiter what you want from the menu, your application tells the API what data it wants to create, read, update, or delete.

What Does REST Stand For?

REST stands for REpresentational State Transfer. Don't worry too much about the formal definition - what matters is understanding how to use it.

Key Characteristics of REST

  • Uses HTTP: REST uses the same protocol your web browser uses to load websites
  • Stateless: Each request is independent - the server doesn't remember previous requests
  • Resource-Based: Everything is treated as a "resource" (like a customer, product, or order)
  • Standard Methods: Uses standard HTTP verbs (GET, POST, PUT, DELETE) to perform actions
  • Returns Data: Usually returns data in JSON format (easy for programs to read)

Understanding Resources: Collections and Objects

In REST, everything is a resource. Resources come in two main types: collections and objects (also called individual resources or items).

Collections

A collection is a group of similar items. Think of it like a filing cabinet drawer that holds multiple folders.

Examples of Collections:
  • /customers - A collection of all customers
  • /products - A collection of all products
  • /orders - A collection of all orders
  • /merchants/12345678901/payors - A collection of all payors for a specific merchant

Collection URLs typically use plural nouns (customers, products, orders).

Objects (Individual Resources)

An object is a single, specific item within a collection. Think of it like one specific folder from that filing cabinet.

Examples of Objects:
  • /customers/12345 - A specific customer with ID 12345
  • /products/ABC-789 - A specific product with ID ABC-789
  • /orders/ORD-2024-001 - A specific order
  • /merchants/12345678901/payors/5513027774438108364 - A specific payor

Object URLs include an identifier (ID) that specifies which exact item you want.

Nested Resources

Resources can be nested to show relationships. For example, payment methods belong to a payor:

/merchants/{merchantId}/payors/{payorId}/savedPaymentMethods/{paymentMethodId}

This URL structure tells us: "Get the payment method with ID {paymentMethodId} that belongs to payor {payorId} under merchant {merchantId}."

HTTP Verbs (Methods)

HTTP verbs (also called methods) tell the API what action you want to perform. Think of them as action words - verbs that describe what you want to do with a resource.

HTTP Verb Purpose What It Does Safe? Idempotent?
GET Read/Retrieve Gets data without changing anything Yes Yes
POST Create Creates a new resource No No
PUT Update/Replace Updates an existing resource (replaces it) No Yes
PATCH Partial Update Updates part of an existing resource No No
DELETE Delete Removes a resource No Yes
Important Terms:
  • Safe: A method is "safe" if it doesn't modify any data on the server. You can call it repeatedly without side effects.
  • Idempotent: A method is "idempotent" if calling it multiple times has the same effect as calling it once. For example, deleting the same resource twice results in the same state (resource is deleted).

GET - Retrieve Data

Use GET to retrieve data without making any changes.

GET /customers

Effect: Returns a list of all customers (does not modify anything)

GET /customers/12345

Effect: Returns details about customer with ID 12345

POST - Create New Resource

Use POST to create a new resource in a collection.

POST /customers

Effect: Creates a new customer with the data you provide in the request body

Returns: Usually returns the newly created resource with its assigned ID

PUT - Update/Replace Resource

Use PUT to update an existing resource (typically replaces the entire resource).

PUT /customers/12345

Effect: Updates customer 12345 with the new data you provide

Returns: Usually returns the updated resource

DELETE - Remove Resource

Use DELETE to remove a resource.

DELETE /customers/12345

Effect: Deletes customer with ID 12345

Returns: Usually returns a success message or the deleted resource

HTTP Verbs and CRUD Operations

CRUD stands for Create, Read, Update, Delete - the four basic operations you can perform on data. HTTP verbs map directly to CRUD operations:

CRUD Operation HTTP Verb Applied to Collection Applied to Object
Create POST POST /customers
Creates a new customer
Not typically used
Read GET GET /customers
Get all customers
GET /customers/12345
Get specific customer
Update PUT or PATCH Not typically used PUT /customers/12345
Update customer 12345
Delete DELETE DELETE /customers
Delete all customers (rare)
DELETE /customers/12345
Delete customer 12345

Common REST API Patterns

Pattern 1: List All Items in a Collection

GET /customers

Purpose: Retrieve a list of all customers

Returns: An array of customer objects

Pattern 2: Get a Specific Item

GET /customers/12345

Purpose: Retrieve details about customer with ID 12345

Returns: A single customer object

Pattern 3: Create a New Item

POST /customers

Purpose: Create a new customer

Send: Customer data in the request body (JSON)

Returns: The newly created customer with its assigned ID

Pattern 4: Update an Existing Item

PUT /customers/12345

Purpose: Update customer 12345

Send: Updated customer data in the request body

Returns: The updated customer object

Pattern 5: Delete an Item

DELETE /customers/12345

Purpose: Delete customer 12345

Returns: Success message or the deleted customer object

Pattern 6: Get Nested Resources

GET /customers/12345/orders

Purpose: Get all orders for customer 12345

Returns: An array of order objects belonging to that customer

Making REST API Calls - Code Examples

Example 1: GET Request - Retrieve a Customer

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

public class RestApiClient
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl = "https://api.example.com";
    private readonly string _bearerToken;

    public RestApiClient(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"));
    }

    // GET - Retrieve a single customer
    public async Task<string> GetCustomerAsync(string customerId)
    {
        string endpoint = $"/customers/{customerId}";
        HttpResponseMessage response = await _httpClient.GetAsync(endpoint);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }

    // GET - Retrieve all customers
    public async Task<string> GetAllCustomersAsync()
    {
        string endpoint = "/customers";
        HttpResponseMessage response = await _httpClient.GetAsync(endpoint);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }
}

// Usage:
var client = new RestApiClient("your-bearer-token");
string customer = await client.GetCustomerAsync("12345");
Console.WriteLine(customer);
Imports System
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Threading.Tasks

Public Class RestApiClient
    Private ReadOnly _httpClient As HttpClient
    Private ReadOnly _baseUrl As String = "https://api.example.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

    ' GET - Retrieve a single customer
    Public Async Function GetCustomerAsync(customerId As String) As Task(Of String)
        Dim endpoint As String = $"/customers/{customerId}"
        Dim response As HttpResponseMessage = Await _httpClient.GetAsync(endpoint)
        response.EnsureSuccessStatusCode()
        Return Await response.Content.ReadAsStringAsync()
    End Function

    ' GET - Retrieve all customers
    Public Async Function GetAllCustomersAsync() As Task(Of String)
        Dim endpoint As String = "/customers"
        Dim response As HttpResponseMessage = Await _httpClient.GetAsync(endpoint)
        response.EnsureSuccessStatusCode()
        Return Await response.Content.ReadAsStringAsync()
    End Function
End Class

' Usage:
Dim client As New RestApiClient("your-bearer-token")
Dim customer As String = Await client.GetCustomerAsync("12345")
Console.WriteLine(customer)
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class RestApiClient {
    private final String baseUrl;
    private final String bearerToken;
    private final HttpClient httpClient;

    public RestApiClient(String baseUrl, String bearerToken) {
        this.baseUrl = baseUrl;
        this.bearerToken = bearerToken;
        this.httpClient = HttpClient.newHttpClient();
    }

    // GET - Retrieve a single customer
    public String getCustomer(String customerId) throws IOException, InterruptedException {
        String endpoint = baseUrl + "/customers/" + customerId;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(endpoint))
            .header("Authorization", "Bearer " + bearerToken)
            .header("Accept", "application/json")
            .GET()
            .build();

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

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

        return response.body();
    }

    // GET - Retrieve all customers
    public String getAllCustomers() throws IOException, InterruptedException {
        String endpoint = baseUrl + "/customers";

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(endpoint))
            .header("Authorization", "Bearer " + bearerToken)
            .header("Accept", "application/json")
            .GET()
            .build();

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

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

        return response.body();
    }
}

// Usage:
RestApiClient client = new RestApiClient("https://api.example.com", "your-bearer-token");
String customer = client.getCustomer("12345");
System.out.println(customer);
require 'net/http'
require 'uri'
require 'json'

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

  # GET - Retrieve a single customer
  def get_customer(customer_id)
    endpoint = "#{@base_url}/customers/#{customer_id}"
    uri = URI.parse(endpoint)

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

    request = Net::HTTP::Get.new(uri.path)
    request['Authorization'] = "Bearer #{@bearer_token}"
    request['Accept'] = 'application/json'

    response = http.request(request)

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

    response.body
  end

  # GET - Retrieve all customers
  def get_all_customers
    endpoint = "#{@base_url}/customers"
    uri = URI.parse(endpoint)

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

    request = Net::HTTP::Get.new(uri.path)
    request['Authorization'] = "Bearer #{@bearer_token}"
    request['Accept'] = 'application/json'

    response = http.request(request)

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

    response.body
  end
end

# Usage:
client = RestApiClient.new('https://api.example.com', 'your-bearer-token')
customer = client.get_customer('12345')
puts customer

Note: The remaining code examples (POST, PUT, DELETE) follow the same patterns shown above with the appropriate HTTP verb changes. See the full page for complete examples.

HTTP Status Codes

When you make a REST API request, the server responds with a status code that tells you whether the request was successful or if something went wrong.

Status Code Category Meaning Examples
2xx Success The request was successful 200 OK - Request succeeded
201 Created - New resource created
204 No Content - Success, but no content to return
3xx Redirection Further action is needed 301 Moved Permanently - Resource moved
304 Not Modified - Cached version is still valid
4xx Client Error There's a problem with your request 400 Bad Request - Invalid data sent
401 Unauthorized - Authentication required
403 Forbidden - You don't have permission
404 Not Found - Resource doesn't exist
409 Conflict - Request conflicts with current state
5xx Server Error The server encountered an error 500 Internal Server Error - Server error
503 Service Unavailable - Server temporarily unavailable

Request and Response Format (JSON)

Most REST APIs use JSON (JavaScript Object Notation) to send and receive data. JSON is a simple text format that's easy for both humans and computers to read.

Example JSON Request Body (POST /customers)

{
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com",
  "phone": "555-1234",
  "address": {
    "street": "123 Main St",
    "city": "Springfield",
    "state": "IL",
    "zipCode": "62701"
  }
}

Example JSON Response Body

{
  "id": "12345",
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com",
  "phone": "555-1234",
  "address": {
    "street": "123 Main St",
    "city": "Springfield",
    "state": "IL",
    "zipCode": "62701"
  },
  "createdDate": "2026-04-02T10:30:00Z",
  "lastModifiedDate": "2026-04-02T10:30:00Z"
}

Authentication

Most REST APIs require authentication to verify who you are. The most common method is using a Bearer Token in the Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Think of the bearer token like a temporary access card - you get it after logging in, and you show it with every request to prove you're authorized.

Best Practices for Working with REST APIs

1. Use HTTPS

Always use HTTPS (not HTTP) to ensure data is encrypted during transmission. This is especially important when sending sensitive information like passwords or payment details.

2. Handle Errors Gracefully

Always check the HTTP status code and handle errors appropriately. Don't assume every request will succeed.

if (response.StatusCode == HttpStatusCode.NotFound)
{
    Console.WriteLine("Customer not found");
}
else if (response.StatusCode == HttpStatusCode.Unauthorized)
{
    Console.WriteLine("Authentication failed - check your token");
}

3. Use Appropriate HTTP Verbs

Use the correct HTTP verb for each operation:

  • GET for reading data (never use GET to modify data)
  • POST for creating new resources
  • PUT for updating existing resources
  • DELETE for removing resources

4. Include Proper Headers

Always include appropriate headers:

  • Content-Type: application/json - When sending JSON data
  • Accept: application/json - When you want JSON responses
  • Authorization: Bearer {token} - For authentication

5. Validate Input Data

Before sending data to an API, validate it on your end to catch errors early:

  • Check that required fields are present
  • Verify email addresses are in correct format
  • Ensure numeric fields contain numbers
  • Check that IDs exist before trying to update or delete

6. Read the API Documentation

Every API is slightly different. Always read the official documentation to understand:

  • What endpoints are available
  • What parameters are required vs. optional
  • What format the data should be in
  • What response codes to expect
  • Rate limits and usage restrictions

Common Mistakes to Avoid

Mistake 1: Using GET to modify data
GET /customers/12345/delete
DELETE /customers/12345
GET requests should never modify data - they're for reading only.
Mistake 2: Not checking HTTP status codes
Always check the status code. A 404 means the resource wasn't found, not that the request succeeded.
Mistake 3: Forgetting authentication headers
Most APIs require authentication. If you get a 401 Unauthorized error, check your bearer token.
Mistake 4: Not handling network errors
Networks can fail. Always wrap API calls in try-catch blocks to handle timeouts and connection errors.
Mistake 5: Hardcoding sensitive data
Never hardcode API keys, tokens, or passwords in your source code. Use environment variables or configuration files.

Summary

Key Takeaways:
  • REST APIs allow programs to communicate over HTTP using standard methods
  • Collections are groups of items (e.g., /customers), objects are specific items (e.g., /customers/12345)
  • HTTP Verbs correspond to actions: GET (read), POST (create), PUT (update), DELETE (delete)
  • CRUD operations map directly to HTTP verbs
  • Status codes tell you if the request succeeded (2xx), had a client error (4xx), or had a server error (5xx)
  • JSON is the most common format for sending and receiving data
  • Authentication (usually via Bearer token) is required for most API operations

With this understanding, you can start exploring and using REST APIs in your applications. Remember to always read the specific API's documentation, as each API may have its own unique requirements and conventions.