This guide provides an overview of using the Kody Payments API and its reference documentation.
- Client Libraries
- Java Installation
- Authenticate to Payments API
- Payments API Reference
- API data reference and Demo code
- More sample code
Kody provides client libraries for many popular languages to access the APIs. If your desired programming language is supported by the client libraries, we recommend that you use this option.
Available languages:
- Java : https://github.com/KodyPay/kody-clientsdk-java/
- Java 6: https://github.com/KodyPay/kody-clientsdk-java6/
- Python: https://github.com/KodyPay/kody-clientsdk-python/
- PHP: https://github.com/KodyPay/kody-clientsdk-php/
- .Net: https://github.com/KodyPay/kody-clientsdk-dotnet/
The advantages of using the Kody Client library instead of a REST API are:
- Maintained by Kody.
- Built-in authentication and increased security.
- Built-in retries.
- Idiomatic for each language.
- Quicker development.
- Backwards compatibility with new versions.
If your coding language is not listed, please let the Kody team know and we will be able to create it for you.
- Java client supports JDK 17 and above
- Gradle (optional), recommended way to install the SDK
Install the Kody Java Client SDK using the following gradle snippet:
dependencies {
implementation("com.kodypay.grpc:kody-clientsdk-java:0.0.8")
}
The library can also be downloaded from here.
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
The client library uses a combination of a Store ID
and an API key
.
These will be shared with you during the technical integration onboarding or by your Kody contact.
During development, you will have access to a test Store and test API key, and when the integration is ready for live access, the production credentials will be shared securely with you and associated with a live store that was onboarded on Kody.
The test and live API calls are always compatible, only changing credentials and the service hostname is required to enable the integration in production.
- Development and test:
https://grpc-staging.kodypay.com
- Live:
https://grpc.kodypay.com
Every client library request authenticates with the server using a storeId
and an API Key
. The storeId
is used as a request parameter and the API Key
is configured when initialising the client.
Example:
String storeId = "UUID of assigned store"; // STORE_ID
PaymentClient paymentClient = new PaymentClient(HOSTNAME, API_KEY);
TerminalsRequest terminalsRequest = TerminalsRequest.newBuilder()
.setStoreId(storeId)
.build();
List<Terminal> response = paymentClient.getTerminals(terminalsRequest);
Replace the STORE_ID
, API_KEY
and HOSTNAME
with the details provided by the Kody team.
Note: it is recommended that you store the API_KEY
in a secured storage, and insert it into your code via an environment variable.
Kody supports the following channels to accept payments via API (using the Java 6 library).
- Terminal - In-person payments
Each of these channels have their own collection of services that are available as method calls on the client library:
PaymentClient
The Kody Payments API Terminal service has the following methods:
- Get List of Terminals:
PaymentClient.getTerminals
- returns all the terminals of the store and their online status - Create Terminal Payment:
PaymentClient.sendTerminalPayment
- initiate a terminal payment - Cancel terminal payment:
PaymentClient.cancelPayment
- cancel an active terminal payment - Get Payment Details
PaymentClient.getDetails
- get the payment details - Refund terminal payment:
PaymentClient.requestRefund
- refund a terminal payment
Follow the links for these methods to see the sample code and the data specification.
Every request to the client library requires authentication and the identifier of the store. See more authentication.
This is a simple and read only method, that returns a list of all terminals assigned to the store, and their online status. You can use this request frequently, and it is a good way to check if your API code is configured properly for authentication.
The terminals request requires the following parameters:
storeId
- the ID of your assigned store
public class TerminalRequest {
private String storeId; // STORE_ID
}
public class Terminal {
private String terminalId; // Terminal serial number
private boolean online; // Online status
}
public class TerminalsResponse {
private List<Terminal> terminals; // List of Terminal objects
}
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
String storeId = "UUID of assigned store"; // STORE_ID
PaymentClient paymentClient = new PaymentClient(HOSTNAME, APIKEY);
TerminalsRequest terminalsRequest = TerminalsRequest.newBuilder()
.setStoreId(storeId)
.build();
List<Terminal> response = paymentClient.getTerminals(terminalsRequest);
Send a payment initiation request to a terminal. This request will either make the terminal immediately display the card acquiring screen, or display a tip screen to the user after which it will go to the card acquiring screen.
A test terminal might have multiple apps on the OS screen. Launch the terminal app called [S] Payments
.
The terminal must be in the mode: Wait for Orders
which can be launched from the terminal app menu.
A store that has the feature Wait for Orders
enabled will always launch the Wait for Orders
screen automatically.
This screen can be closed (by tapping the X
icon) to access other terminal features, but payments from API will not work until the Wait for Orders
screen is started.
public class PayRequest {
private String amount = null;
private Boolean showTips = null;
private PaymentMethod paymentMethod = null;
}
public class PaymentMethod {
private PaymentMethodType paymentMethodType = null;
}
public enum PaymentMethodType {
CARD("CARD"),
ALIPAY("ALIPAY"),
WECHAT("WECHAT")
}
Request parameters:
storeId
- the UUID of your assigned storeterminalId
- the serial number of the terminal that will process the payment request. This number is returned by the list of terminals request, or can be found on the back label of the hardware.amount
- amount as a 2.dp decimal number, such as"1.00"
showTips
- (optional) whether to show (true) or hide (false) the tip options. Default is (false)payment_method
- (optional) Settings to enable going straight to QR scanningpayment_method_type
- Payment method type: CARD (default), ALIPAY, WECHAT
public enum PaymentStatus {
PENDING(0),
SUCCESS(1),
FAILED(2),
CANCELLED(3)
}
public class PayResponse {
private PaymentStatus status = null; // Status of payment
private String failureReason = null; // Optional, reason for failure
private Map<String, Object> receiptJson = null; // Optional, json blob for receipt data
private String orderId = null; // Unique order ID generated by Kody
private OffsetDateTime dateCreated = null; // Timestamp when the response was created
private String extPaymentRef = null; // Optional, external payment reference
private OffsetDateTime datePaid = null; // Optional, timestamp for date paid
private String totalAmount = null; // Optional, total amount
private String saleAmount = null; // Optional, sale amount
private String tipsAmount = null; // Optional, tips amount
}
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
PaymentClient paymentClient = new PaymentClient(HOSTNAME, APIKEY);
String storeId = "UUID of assigned store";
String terminalId = "Terminal serial number";
String amount = "1.00";
boolean showTips = false;
PaymentMethodType paymentMethodType = PaymentMethodType.CARD;
PayRequest payRequest = PayRequest.newBuilder()
.setStoreId(storeId)
.setAmount(amount)
.setTerminalId(terminalId)
.setShowTips(showTips)
.setPaymentMethod(PaymentMethod.newBuilder().setPaymentMethodType(paymentMethodType).build())
.build();
PayResponse response = paymentClient.sendPayment(payRequest);
// Note: the response will be returned with a PENDING payment status
// the payment details should be retrieved by the client until the payment either completes (SUCCESS/FAILED) or is CANCELLED (see below).
The payment details request requires the following parameters:
storeId
- the ID of your assigned storeorderId
- the Order ID returned in the initial payment response, a unique UUID value for each payment.
public class PaymentDetailsRequest {
private String storeId;
private String orderId;
}
- PayResponse : Get Payment Detail Response
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
PaymentClient paymentClient = new PaymentClient(HOSTNAME, APIKEY);
String storeId = "UUID of assigned store";
String orderId = "UUID of order generated by Kody";
PaymentDetailsRequest paymentDetailsRequest = PaymentDetailsRequest.newBuilder()
.setStoreId(storeId)
.setOrderId(orderId)
.build();
PayResponse response = paymentClient.getDetails(paymentDetailsRequest);
Cancel an ongoing terminal payment, before it has been paid on the terminal.
public class CancelRequest {
private String amount = null;
private String orderId = null;
}
The cancel payment request requires the following parameters:
storeId
- the ID of your assigned storeterminalId
- the serial number of the terminal that is processing the payment requestamount
- the amount sent in the original payment request, used to find the payment requestorderId
- the Order ID returned in the initial payment response, a unique UUID value for each payment
public enum PaymentStatus {
PENDING(0),
SUCCESS(1),
FAILED(2),
CANCELLED(3)
}
public class CancelResponse {
private PaymentStatus status; //Cancellation status
}
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
PaymentClient paymentClient = new PaymentClient(HOSTNAME, APIKEY);
String storeId = "UUID of assigned store"; //STORE_ID
String terminalId = "Terminal serial number";
String amount = "1.00";
String orderId = "UUID of order generated by Kody";
CancelRequest cancelRequest = CancelRequest.newBuilder()
.setStoreId(storeId)
.setAmount(amount)
.setTerminalId(terminalId)
.setOrderId(orderId)
.build();
PaymentStatus response = paymentClient.cancelPayment(cancelRequest);
public class RefundRequest {
private String storeId;
private String orderId;
private String amount;
}
The refund payment request requires the following parameters:
storeId
- the ID of your assigned storeorderId
- the Order ID returned in the initial payment response, a unique UUID value for each paymentamount
- the amount to refund, should be less than or equal to the original payment amount
public enum RefundStatus {
PENDING(0),
REQUESTED(1),
FAILED(2)
}
public class RefundResponse {
private RefundStatus status; // Refund status
private String orderId; // The order ID sent in the request
private String failureReason; // If the refund fails, this will show the reason why
private OffsetDateTime dateCreated; // Date when the refund was requested
private String totalPaidAmount; // How much was paid for the order
private String totalAmountRequested; // The total amount of refunds requested for this order
private String totalAmountRefunded; // The total amount of refunds applied to this order
private String remainingAmount; // The amount remaining for this order
private String paymentTransactionId; // The ID of the payment that needs refunding
}
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
PaymentClient paymentClient = new PaymentClient(HOSTNAME, APIKEY);
String storeId = "UUID of assigned store"; //STORE_ID
String orderId = "UUID of order generated by Kody";
String amount = "1.00";
RefundRequest refundRequest = RefundRequest.newBuilder()
.setStoreId(storeId)
.setAmount(amount)
.setOrderId(orderId)
.build();
RefundResponse response = paymentClient.requestTerminalRefund(refundRequest);
- Ecom - In-person payments
Each of these channels have their own collection of services that are available as method calls on the client library:
PaymentClient
The Kody Payments API Ecom service has the following methods:
- Create Online Payment:
PaymentClient.sendOnlinePayment
- initiate an online payment - Get Payment Details
PaymentClient.paymentDetails
- get payment details - Get Payments
PaymentClient.getPayments
- get payments - Refund online payment:
PaymentClient.refundOnlinePayment
- refund an online payment
Follow the links for these methods to see the sample code and the data specification.
Every request to the client library requires authentication and the identifier of the store. See more authentication.
Send a payment initiation request for an online payment. Returns an object with a URL to display an online payment page to the shopper.
public class PaymentInitiationRequest {
private String storeId = "UUID of assigned store";
private String orderId = "a unique reference for the payment";
private String paymentReference = "a unique reference for the payment";
private String amount = "1.00";
private String currency = "GBP";
private String returnUrl = "returnUrl";
private ExpirySettings expirySettings;
}
public class ExpirySettings {
private bool showTimer;
private int expiringSeconds;
}
Request parameters:
storeId
- the ID of your assigned storepaymentReference
- a unique reference for the payment, sent from the client and returned by the serveramount
- the amount to request for the online payment, formatted as a 2.dp decimal number, such as1.00
currency
- the currency for this payment in 3 character ISO format, such asGBP
orderId
- a unique order ID for this payment, sent from the client and returned by the serverreturnUrl
- where the payment form will redirect to after the payment has completed, the return url will have additional query parameters appended to indicate the status of the payment request.expiry
- (optional) setting expiry settingsshowTimer
- (optional) flag to show countdown timer in payment pageexpiringSeconds
- (optional) how long the payment form will wait until the payment expires and the page will redirect to the return url
public enum ErrorType {
UNKNOWN("UNKNOWN"),
DUPLICATE_ATTEMPT("DUPLICATE_ATTEMPT"),
INVALID_REQUEST("INVALID_REQUEST"),
CANCELLED("CANCELLED")
}
public class Error {
private ErrorType type; //Enum for the error type
private String message; //Error message
}
public class PaymentInitiationResponse {
private Response response;
private Error error;
}
public class Response {
private String paymentId; // Unique identifier created by Kody
private String paymentUrl; // The URL to send to the user from your application
}
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
PaymentClient paymentClient = new PaymentClient(HOSTNAME, APIKEY);
String storeId = "UUID of assigned store";
String orderId = "a unique reference for the order";
String paymentReference = "a unique reference for the payment";
String amount = "1.00";
String currency = "GBP";
String returnUrl = "returnUrl";
ExpirySettings expirySettings = PaymentInitiationRequest.ExpirySettings.newBuilder()
.setShowTimer(true)
.setExpiringSeconds(1800)
.build();
PaymentInitiationRequest paymentInitiationRequest = PaymentInitiationRequest.newBuilder()
.setStoreId(storeId)
.setPaymentReference(paymentReference)
.setAmount(amount)
.setCurrency(currency)
.setOrderId(orderId)
.setReturnUrl(returnUrl)
.setExpiry(expirySettings)
.build();
PaymentInitiationResponse response = paymentClient.sendOnlinePayment(paymentInitiationRequest);
The payment details request requires the following parameters:
storeId
- the ID of your assigned storepaymentIdentifier
- One of the two parameters below must be set. They are mutually exclusivepaymentId
- The unique identifier created by KodypaymentReference
- Your unique payment reference that was set during the initiation
public class PaymentDetailsRequest {
private String storeId;
private String paymentId;
private String paymentReference;
}
public class PaymentDetailsResponse {
private String paymentId; // Unique identifier created by Kody
private String paymentReference; // payment reference
private String orderId; // Unique order ID generated by Kody
private String orderMetadata; // order related metadata
private PaymentStatus status; // Status of payment
private String paymentDataJson; // Optional, json blob for payment data
private OffsetDateTime dateCreated; // Timestamp when the payment was created
private OffsetDateTime datePaid; // Timestamp when the payment was paid
private String pspReference; // Payment Service Provider Reference
}
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
PaymentClient paymentClient = new PaymentClient(HOSTNAME, APIKEY);
String storeId = "UUID of assigned store";
String paymentId = "Payment Id";
PaymentDetailsRequest paymentDetailsRequest = PaymentDetailsRequest.newBuilder()
.setStoreId(storeId)
.setPaymentId(paymentId)
.build();
PaymentDetailsResponse payments = paymentClient.paymentDetails(paymentDetailsRequest);
The payment details request requires the following parameters:
storeId
- the ID of your assigned storepageCursor
- set pagination settings.page
- set an offset of the results. Value of 0 will return payments from the beginning of the data set.pageSize
- the number of results to be returned per page. Value of 1 will return one record.
public class PaymentDetailsRequest {
private String storeId;
private PageCursor pageCursor;
}
public class PageCursor {
private int page;
private int pageSize;
}
public class PaymentDetails {
private String paymentId; // Unique identifier created by Kody
private String paymentReference; // payment reference
private String orderId; // Unique order ID generated by Kody
private String orderMetadata; // order related metadata
private PaymentStatus status; // Status of payment
private String paymentDataJson; // Optional, json blob for payment data
private OffsetDateTime dateCreated; // Timestamp when the payment was created
private OffsetDateTime datePaid; // Timestamp when the payment was paid
}
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
PaymentClient paymentClient = new PaymentClient(HOSTNAME, APIKEY);
String storeId = "UUID of assigned store";
PageCursor pageCursor = PageCursor.newBuilder()
.setPageSize(1)
.build();
GetPaymentsRequest getPaymentsRequest = GetPaymentsRequest.newBuilder()
.setStoreId(storeId)
.setPageCursor(pageCursor)
.build();
List<PaymentDetails> response = paymentClient.getPayments(getPaymentsRequest);
public class RefundRequest {
private String storeId;
private String paymentId;
private String amount;
}
The refund payment request requires the following parameters:
storeId
- the ID of your assigned storepaymentId
- unique identifier created by Kodyamount
- amount as a 2.dp decimal number, such as"1.00"
public enum RefundStatus {
PENDING(0),
REQUESTED(1),
FAILED(2)
}
public class RefundResponse {
private RefundStatus status; // Refund status
private String paymentId; // Unique identifier created by Kody
private String failureReason; // If the refund fails, this will show the reason why
private OffsetDateTime dateCreated; // Date when the refund was requested
private String totalPaidAmount; // How much was paid for the order
private String totalAmountRequested; // The total amount of refunds requested for this order
private String totalAmountRefunded; // The total amount of refunds applied to this order
private String remainingAmount; // The amount remaining for this order
private String paymentTransactionId; // The ID of the payment that needs refunding
}
import common.PaymentClient;
import com.kodypay.grpc.pay.v1.*;
PaymentClient paymentClient = new PaymentClient(HOSTNAME, APIKEY);
String storeId = "UUID of assigned store"; //STORE_ID
String paymentId = "Unique identifier created by Kody";
String amount = "1.00";
RefundRequest refundRequest = RefundRequest.newBuilder()
.setStoreId(storeId)
.setPaymentId(paymentId)
.setAmount(amount)
.build();
RefundResponse response = paymentClient.requestOnlineRefund(refundRequest);
- Java : https://github.com/KodyPay/kody-clientsdk-java/tree/main/samples/src/main/java/terminal
- Java6 : https://github.com/KodyPay/kody-clientsdk-java6/tree/main/samples/src/main/java/terminal
- Python: https://github.com/KodyPay/kody-clientsdk-python/tree/main/versions/3_12/samples/terminal
- PHP: https://github.com/KodyPay/kody-clientsdk-php/tree/main/samples/php8/pos
- .Net: https://github.com/KodyPay/kody-clientsdk-dotnet/tree/main/samples/ListTerminals,https://github.com/KodyPay/kody-clientsdk-dotnet/tree/main/samples/TerminalPayment