> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://beta-docs.payabli.com/developer-guides/entities-customers/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://beta-docs.payabli.com/_mcp/server. # Manage Customers with the API In Payabli, customers are the entities that buy goods and services and make payments to your paypoints (merchants). This guide explains how to manage customers with the API. ## Custom identifiers By default, when working with the API on any task that involves customer data, you must include at least one of these identifier fields: * `firstname` and `lastname` * `email` * `customerId` These tasks include things like making transactions, working with customer records, managing invoices, and more. Payabli first searches to match customer records based on your custom identifiers. If you don't have any custom identifiers set, then Payabli falls back to matching on `customerId`. > **Note** > > Custom identifiers are managed in PartnerHub by navigating to **Settings > Custom Fields**. Payabli recommends using the system-generated `customerId` field to identify customers for ease of integration and consistency. However, you can configure custom identifiers, which lets you decide which customer profile fields to use to uniquely identify and associate customer records and payments. Custom identifiers cascade from org parent to child entities, so you can set them at the organization level and have them apply to all child paypoints. This is useful if you want to use a specific field across all your customers, such as `email` or `clientId`. For example. if your company uses the customer's email address as their unique identifier, you can choose `email` as the identifier. If your organization prefers to identify customers by a field called `clientId`, you can create that custom field in Payabli and set it as an identifier. This means that every API call that involves a customer must include the `clientID` because Payabli uses that field to search for customers. ![image of the custom identifiers screen](/_fern-img/220db7e2b827bd3dc3bebbaafabf6ed5ea1c09c2264e93732eee13fc43476f85.webp) Pass custom identifiers in the `customerData.additionalData` object like this: ```json "customerData": { "additionalData": { "YourCustomIdentifier": "123" } } ``` ## Create a customer To create a customer record, send a POST request to the `/api/Customer/single/{entry}` endpoint. For complete details, see the [API reference](/api-reference/customer/add-customer) for this endpoint. The add customer request has these optional parameters: **`replaceExisting`** `integer` — default: 0 When set to `1`, an existing customer record will be overwritten with a new customer record (if the identifiers find a match). Possible values: 0 (don't replace), 1 (replace). Default is `0`. --- **`forceCustomerCreation`** `boolean` — default: false When set to `true`, a new customer record will be created even if an existing customer record is found. Possible values: `true` or `false`. Default is `false`. --- The body is where you include information about the customer, including [identifiers](/developer-guides/entities-custom-identifiers). An identifier is required to create customer records. You can change your identifier settings in **Settings > Custom Fields** in PartnerHub. When you create a new customer record, Payabli first looks for an existing customer based on matching any of your configured identifier fields. If Payabli doesn't find a match, then it attempts to match based on the `CustomerNumber` field, if included. If there is no match, Payabli creates a new customer. This example creates a customer record. It includes `firstname` and `lastname` as the minimum required identifiers, as set in the example account. ### Request POST [https://api-sandbox.payabli.com/api/Customer/single/\{entry}](https://api-sandbox.payabli.com/api/Customer/single/\{entry}) **`CreateCustomer`** ```curl CreateCustomer curl -X POST https://api-sandbox.payabli.com/api/Customer/single/8cfec329267 \ -H "requestToken: " \ -H "Content-Type: application/json" \ -d '{ "address1": "123 Bishop'\''s Trail", "city": "Mountain City", "country": "US", "customerNumber": "12356ACB", "email": "irene@canizalesconcrete.com", "firstname": "Irene", "identifierFields": [ "email" ], "lastname": "Canizales", "state": "TN", "timeZone": -5, "zip": "37612" }' ``` **`CreateCustomer`** ```python CreateCustomer import requests url = "https://api-sandbox.payabli.com/api/Customer/single/8cfec329267" payload = { "address1": "123 Bishop's Trail", "city": "Mountain City", "country": "US", "customerNumber": "12356ACB", "email": "irene@canizalesconcrete.com", "firstname": "Irene", "identifierFields": ["email"], "lastname": "Canizales", "state": "TN", "timeZone": -5, "zip": "37612" } headers = { "requestToken": "", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`CreateCustomer`** ```javascript CreateCustomer const url = 'https://api-sandbox.payabli.com/api/Customer/single/8cfec329267'; const options = { method: 'POST', headers: {requestToken: '', 'Content-Type': 'application/json'}, body: '{"address1":"123 Bishop\'s Trail","city":"Mountain City","country":"US","customerNumber":"12356ACB","email":"irene@canizalesconcrete.com","firstname":"Irene","identifierFields":["email"],"lastname":"Canizales","state":"TN","timeZone":-5,"zip":"37612"}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` **`CreateCustomer`** ```go CreateCustomer package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api-sandbox.payabli.com/api/Customer/single/8cfec329267" payload := strings.NewReader("{\n \"address1\": \"123 Bishop's Trail\",\n \"city\": \"Mountain City\",\n \"country\": \"US\",\n \"customerNumber\": \"12356ACB\",\n \"email\": \"irene@canizalesconcrete.com\",\n \"firstname\": \"Irene\",\n \"identifierFields\": [\n \"email\"\n ],\n \"lastname\": \"Canizales\",\n \"state\": \"TN\",\n \"timeZone\": -5,\n \"zip\": \"37612\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("requestToken", "") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` **`CreateCustomer`** ```ruby CreateCustomer require 'uri' require 'net/http' url = URI("https://api-sandbox.payabli.com/api/Customer/single/8cfec329267") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["requestToken"] = '' request["Content-Type"] = 'application/json' request.body = "{\n \"address1\": \"123 Bishop's Trail\",\n \"city\": \"Mountain City\",\n \"country\": \"US\",\n \"customerNumber\": \"12356ACB\",\n \"email\": \"irene@canizalesconcrete.com\",\n \"firstname\": \"Irene\",\n \"identifierFields\": [\n \"email\"\n ],\n \"lastname\": \"Canizales\",\n \"state\": \"TN\",\n \"timeZone\": -5,\n \"zip\": \"37612\"\n}" response = http.request(request) puts response.read_body ``` **`CreateCustomer`** ```java CreateCustomer import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api-sandbox.payabli.com/api/Customer/single/8cfec329267") .header("requestToken", "") .header("Content-Type", "application/json") .body("{\n \"address1\": \"123 Bishop's Trail\",\n \"city\": \"Mountain City\",\n \"country\": \"US\",\n \"customerNumber\": \"12356ACB\",\n \"email\": \"irene@canizalesconcrete.com\",\n \"firstname\": \"Irene\",\n \"identifierFields\": [\n \"email\"\n ],\n \"lastname\": \"Canizales\",\n \"state\": \"TN\",\n \"timeZone\": -5,\n \"zip\": \"37612\"\n}") .asString(); ``` **`CreateCustomer`** ```php CreateCustomer request('POST', 'https://api-sandbox.payabli.com/api/Customer/single/8cfec329267', [ 'body' => '{ "address1": "123 Bishop\'s Trail", "city": "Mountain City", "country": "US", "customerNumber": "12356ACB", "email": "irene@canizalesconcrete.com", "firstname": "Irene", "identifierFields": [ "email" ], "lastname": "Canizales", "state": "TN", "timeZone": -5, "zip": "37612" }', 'headers' => [ 'Content-Type' => 'application/json', 'requestToken' => '', ], ]); echo $response->getBody(); ``` **`CreateCustomer`** ```csharp CreateCustomer using RestSharp; var client = new RestClient("https://api-sandbox.payabli.com/api/Customer/single/8cfec329267"); var request = new RestRequest(Method.POST); request.AddHeader("requestToken", ""); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"address1\": \"123 Bishop's Trail\",\n \"city\": \"Mountain City\",\n \"country\": \"US\",\n \"customerNumber\": \"12356ACB\",\n \"email\": \"irene@canizalesconcrete.com\",\n \"firstname\": \"Irene\",\n \"identifierFields\": [\n \"email\"\n ],\n \"lastname\": \"Canizales\",\n \"state\": \"TN\",\n \"timeZone\": -5,\n \"zip\": \"37612\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`CreateCustomer`** ```swift CreateCustomer import Foundation let headers = [ "requestToken": "", "Content-Type": "application/json" ] let parameters = [ "address1": "123 Bishop's Trail", "city": "Mountain City", "country": "US", "customerNumber": "12356ACB", "email": "irene@canizalesconcrete.com", "firstname": "Irene", "identifierFields": ["email"], "lastname": "Canizales", "state": "TN", "timeZone": -5, "zip": "37612" ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api-sandbox.payabli.com/api/Customer/single/8cfec329267")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` A successful request returns a JSON response. The `customerId` value is the Payabli-generated identifier that you can use with other endpoints to manage the customer and make transactions. ### Response (200) ```json { "isSuccess": true, "responseData": { "AdditionalFields": { "key": "value" }, "Address1": "123 Bishop's Trail", "Balance": 0, "City": "Mountain City", "Country": "US", "Created": "2024-03-13T12:49:56Z", "customerId": 17264, "customerNumber": "12356ACB", "customerStatus": 0, "customerSummary": { "numberofTransactions": 30, "recentTransactions": [ { "EntrypageId": 0, "FeeAmount": 1, "PayorId": 1551, "PaypointId": 226, "SettlementStatus": 2, "TotalAmount": 30.22, "TransStatus": 1 } ], "totalAmountTransactions": 1500, "totalNetAmountTransactions": 1500 }, "Email": "irene@canizalesconcrete.com", "Firstname": "Irene", "IdentifierFields": [ "email" ], "Lastname": "Canizales", "LastUpdated": "2024-03-13T12:49:56Z", "MFA": false, "MFAMode": 0, "pageidentifier": "null", "ParentOrgName": "The Pilgrim Planner", "PaypointDbaname": "Gruzya Adventure Outfitters", "PaypointEntryname": "41035afaa7", "PaypointLegalname": "Gruzya Adventure Outfitters, LLC", "State": "TN", "TimeZone": -5, "Zip": "37612" }, "responseText": "Success" } ``` ## Import customers You can import a list of customers into Payabli using the API. This is useful if you have a large number of customers to add at once, or if you want to automate the process. Before you get started, download the example CSV file and open it with the editor of your choice. Use it as an example to help you build your import file. Download CSV To import a list of customer, send a POST request to the `/api/Import/customersForm/{entrypoint}` endpoint, with an attached CSV file. When importing customers, there is an optional query parameter: **`replaceExisting`** `integer` — default: 0 `replaceExisting` - Flag indicating whether to replace existing customer with a new record. Possible values: * `0` (don't replace) * `1` (replace). --- This example imports customerImport.csv for the entrypoint `e56ce00572`. ### Request POST [https://api-sandbox.payabli.com/api/Import/customersForm/\{entry}](https://api-sandbox.payabli.com/api/Import/customersForm/\{entry}) **`ImportCustomer`** ```curl ImportCustomer curl -X POST https://api-sandbox.payabli.com/api/Import/customersForm/8cfec329267 \ -H "requestToken: " \ -H "Content-Type: multipart/form-data" \ -F file=@ ``` **`ImportCustomer`** ```python ImportCustomer import requests url = "https://api-sandbox.payabli.com/api/Import/customersForm/8cfec329267" files = { "file": "open('', 'rb')" } headers = {"requestToken": ""} response = requests.post(url, files=files, headers=headers) print(response.json()) ``` **`ImportCustomer`** ```javascript ImportCustomer const url = 'https://api-sandbox.payabli.com/api/Import/customersForm/8cfec329267'; const form = new FormData(); form.append('file', ''); const options = {method: 'POST', headers: {requestToken: ''}}; options.body = form; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` **`ImportCustomer`** ```go ImportCustomer package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api-sandbox.payabli.com/api/Import/customersForm/8cfec329267" payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("requestToken", "") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` **`ImportCustomer`** ```ruby ImportCustomer require 'uri' require 'net/http' url = URI("https://api-sandbox.payabli.com/api/Import/customersForm/8cfec329267") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["requestToken"] = '' request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n" response = http.request(request) puts response.read_body ``` **`ImportCustomer`** ```java ImportCustomer import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api-sandbox.payabli.com/api/Import/customersForm/8cfec329267") .header("requestToken", "") .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n") .asString(); ``` **`ImportCustomer`** ```php ImportCustomer request('POST', 'https://api-sandbox.payabli.com/api/Import/customersForm/8cfec329267', [ 'multipart' => [ [ 'name' => 'file', 'filename' => '', 'contents' => null ] ] 'headers' => [ 'requestToken' => '', ], ]); echo $response->getBody(); ``` **`ImportCustomer`** ```csharp ImportCustomer using RestSharp; var client = new RestClient("https://api-sandbox.payabli.com/api/Import/customersForm/8cfec329267"); var request = new RestRequest(Method.POST); request.AddHeader("requestToken", ""); request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`ImportCustomer`** ```swift ImportCustomer import Foundation let headers = ["requestToken": ""] let parameters = [ [ "name": "file", "fileName": "" ] ] let boundary = "---011000010111000001101001" var body = "" var error: NSError? = nil for param in parameters { let paramName = param["name"]! body += "--\(boundary)\r\n" body += "Content-Disposition:form-data; name=\"\(paramName)\"" if let filename = param["fileName"] { let contentType = param["content-type"]! let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8) if (error != nil) { print(error as Any) } body += "; filename=\"\(filename)\"\r\n" body += "Content-Type: \(contentType)\r\n\r\n" body += fileContent } else if let paramValue = param["value"] { body += "\r\n\r\n\(paramValue)" } } let request = NSMutableURLRequest(url: NSURL(string: "https://api-sandbox.payabli.com/api/Import/customersForm/8cfec329267")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` A successful request returns a JSON response with the number of added and rejected records, and any errors. The imported data is now available for use, and you can confirm by checking PartnerHub or PayHub. ### Response (200) ```json { "isSuccess": true, "pageIdentifier": "null", "responseCode": 1, "responseData": { "added": 26, "errors": [ "errors", "errors" ], "rejected": 2 }, "responseText": "Success" } ``` > **Check** > > The `responseData` object contains the number of records added and rejected. The `errors` field contains any errors that occurred during the import process. After you import customers, you can manage them with the API. For example, you can update customer information, check customer status, and run payments for customers. ## Customer status In customer endpoints and endpoints that return customer data, the customer status field is `customerStatus`.
Value Key
Inactive 0
Active 1
Deleted -99
Locked 85
## Managing customers You can also manage customers via the API. See these endpoint references for more information: * [Update Customer](/api-reference/customer/update-customer-record) * [Delete Customer](/api-reference/customer/delete-customer-record) * [Get Customer](/api-reference/customer/get-customer-record) > If you're a software company, you're a payments company™