ePay logo
Developer Portal

Build, test, and deploy
with our flexible API

Everything you need to integrate ePay - all in one place. Use our API, plugins, and guides to set up payments in your solution - no matter the platform.

Integrations
Get started quickly with one of our plug-and-play integrations - built for popular ecommerce platforms.
WooCommerceMagentoShopwareShopify
API
Our well-documented REST API gives you full control and flexibility - build exactly what you need.
ePay.js
Our JavaScript SDK makes it easy to integrate ePay directly into your frontend. Simple setup and clear documentation.
main.js
1
2
3
4
5
epay
.setSessionId("<SESSION_ID>")
.setSessionKey("<SESSION_KEY>")
.setCallbacks({...})
.init();
JavaScriptUTF-8
Ln 5, Col 8Spaces: 2
Native SDK

Payments inside your app

Build a checkout for Android and iOS with Kotlin and Swift. Add card fields to your own layout and let ePay’s Native SDK handle card collection and the payment flow.

Explore Native SDK

Get started quickly and easily
integrating your payment solution

At ePay, we build products we would love to integrate ourselves.

We're developers, and we know what it takes: Clear documentation, flexible tools, and a platform that fits your needs - whether you're working on a single webshop or managing multiple clients.

Getting started with integration

We’ve made it easy to integrate ePay - no matter which solution you choose. Our documentation guides you step-by-step:

  • Checkout - integrate our payment window. Go to guide
  • Blocks - embed payment methods directly on your website. Go to guide
  • Verify - handle age verification when selling alcohol & tobacco. Go to guide
  • Link - send payment links directly to the customer. Go to guide
  • Subscription – set up recurring payments. Read the guide

More guides and resources

One profile, multiple accounts
When you create a profile, you can add multiple accounts. Perfect if you're handling multiple webshops or solutions.
Sign up with your GitHub account
Create your ePay profile using your GitHub or Google account. It's quick and easy - no need to remember another login.
Test as long as you want
Our test environment works exactly like the real one, so you can build and test confidently until you're ready to go live. Completely free, no obligations.
Working with multiple clients?
If you're an agency, developer, or consultant with multiple clients, become an ePay partner. Get attractive commission and tools to work more efficiently.
Interactive demos

See how easy it is to integrate

Blocks – embedded card fields

script.js
1// ------------------------------- 2// Hosted Fields Callback Functions 3// ------------------------------- 4 5function clientReadyCallback(event) { 6 console.log("Hosted fields client is ready:", event); 7} 8 9function invalidSessionCallback(event) { 10 console.error("Invalid session detected:", event); 11 displayError("Invalid session detected", event); 12} 13 14function challengeIssuedCallback(event) { 15 console.log("A challenge has been issued:", event); 16} 17 18function transactionAcceptedCallback(event) { 19 onTransactionComplete(true); 20} 21 22function transactionDeclinedCallback(event) { 23 onTransactionComplete(false); 24} 25 26function clientRedirectCallback(event) { 27 return false; // Skipping redirects in the demo preview 28} 29 30function invalidInputCallback(event) { 31 console.error("Invalid input encountered:", event); 32 displayError("Invalid input encountered", event); 33} 34 35function inputValidityCallback(event) { 36 console.log("Input validity changed:", event); 37} 38 39function inputSubmitCallback(event) { 40 console.log("Input submitted:", event); 41} 42 43function sessionExpiredCallback(event) { 44 console.error("Session has expired:", event); 45 displayError("Session has expired", event); 46} 47 48function errorCallback(event) { 49 console.error("An error occurred in hosted fields:", event); 50 displayError("An error occurred in hosted fields", event); 51} 52 53// ------------------------------- 54// Helper: Create UI Containers 55// ------------------------------- 56 57function createUi() { 58 const fields = document.createElement("div"); 59 fields.id = "fields"; 60 61 const errorBlock = document.createElement("div"); 62 errorBlock.id = "error-block"; 63 64 document.body.appendChild(fields); 65 document.body.appendChild(errorBlock); 66 67 return { fields, errorBlock }; 68} 69 70// ------------------------------- 71// Helper: Display Errors 72// ------------------------------- 73 74/** 75 * Appends a formatted error message to the error block. 76 * 77 * @param {string} description - A human-readable error description. 78 * @param {object} event - The event object containing error details. 79 */ 80function displayError(description, event) { 81 const errorBlock = document.getElementById("error-block"); 82 errorBlock.style.display = "block"; 83 84 let title = ""; 85 if (event && event.type) { 86 title += event.type; 87 } 88 if (event && event.errorCode) { 89 title += title ? " - " + event.errorCode : event.errorCode; 90 } 91 if (!title) { 92 title = "Error"; 93 } 94 95 if (event && event.event) { 96 title += ` (Event: ${event.event})`; 97 } else { 98 title += " (Event: N/A)"; 99 } 100 101 const errorItem = document.createElement("div"); 102 errorItem.classList.add("error-item"); 103 104 const titleEl = document.createElement("div"); 105 titleEl.classList.add("error-title"); 106 titleEl.textContent = title; 107 108 const descriptionEl = document.createElement("div"); 109 descriptionEl.classList.add("error-description"); 110 descriptionEl.textContent = 111 description || 112 (event && event.message ? event.message : "No further details provided."); 113 114 errorItem.appendChild(titleEl); 115 errorItem.appendChild(descriptionEl); 116 errorBlock.appendChild(errorItem); 117} 118 119// ------------------------------- 120// Payment Request Setup 121// ------------------------------- 122 123const headers = new Headers(); 124const demoApiKey = "test_93dc98ae-ff87-4671-a821-cda33fdfc26e"; // Demo API key: NEVER use this client-side in production 125 126headers.append("Content-Type", "application/json"); 127headers.append("Accept", "application/json"); 128headers.append("Authorization", `Bearer ${demoApiKey}`); 129 130const paymentData = { 131 pointOfSaleId: "0195a362-5bf4-7bb9-a419-2367fda11e6f", 132 amount: 100, // minor amount 133 currency: "DKK", 134 scaMode: "SKIP", 135}; 136 137const requestOptions = { 138 method: "POST", 139 headers: headers, 140 body: JSON.stringify(paymentData), 141 redirect: "follow", 142}; 143 144// ------------------------------- 145// Helper: Dynamically Load External Module 146// ------------------------------- 147 148/** 149 * Dynamically loads an external script module. 150 * 151 * @param {string} scriptUrl - The URL of the external module. 152 * @param {Function} onLoadCallback - A callback function to run once the module loads. 153 */ 154function loadExternalModule(scriptUrl, onLoadCallback) { 155 const scriptEl = document.createElement("script"); 156 scriptEl.type = "module"; 157 scriptEl.src = scriptUrl; 158 scriptEl.onload = onLoadCallback; 159 document.body.appendChild(scriptEl); 160} 161 162// ------------------------------- 163// Helper: Create Payment Button 164// ------------------------------- 165 166/** 167 * Creates and appends a payment button to the DOM. 168 * The button text is set dynamically using the converted amount (major) and currency. 169 * 170 * @param {number} amount - The payment amount (in minor units). 171 * @param {string} currency - The currency code. 172 */ 173function createPaymentButton(amount, currency) { 174 const majorAmount = (amount / 100).toFixed(2); 175 176 const button = document.createElement("button"); 177 button.type = "button"; 178 button.id = "payment-button"; 179 button.textContent = `Pay ${majorAmount} ${currency}`; 180 181 button.addEventListener("click", () => { 182 epay.createCardTransaction(); 183 }); 184 185 const fieldsContainer = document.getElementById("fields"); 186 fieldsContainer.insertAdjacentElement("afterend", button); 187} 188 189// ------------------------------- 190// Helper: Handle Transaction Completed 191// ------------------------------- 192 193/** 194 * Function to handle the display after a transaction is completed. 195 * 196 * @param {boolean} success - Indicates whether the transaction was successful. 197 */ 198function onTransactionComplete(success) { 199 const fieldsContainer = document.getElementById("fields"); 200 const paymentButton = document.getElementById("payment-button"); 201 202 fieldsContainer.style.display = "none"; 203 paymentButton.style.display = "none"; 204 205 const messageContainer = document.createElement("div"); 206 messageContainer.id = "transaction-message"; 207 messageContainer.style.marginTop = "20px"; 208 209 if (success) { 210 messageContainer.innerHTML = ` 211 <h2>Payment Success</h2> 212 <p>Your transaction has been completed successfully.</p> 213 `; 214 } else { 215 messageContainer.innerHTML = ` 216 <h2>Payment Failed</h2> 217 <p>We're sorry, but your transaction could not be completed.</p> 218 `; 219 } 220 221 if (fieldsContainer && fieldsContainer.parentNode) { 222 fieldsContainer.parentNode.appendChild(messageContainer); 223 } else { 224 document.body.appendChild(messageContainer); 225 } 226} 227 228// ------------------------------- 229// Payment Request & Hosted Fields Initialization 230// ------------------------------- 231 232createUi(); 233 234fetch("https://payments.epay.eu/public/api/v1/cit", requestOptions) 235 .then((response) => response.json()) 236 .then((result) => { 237 const sessionId = result.session.id; 238 const sessionKey = result.key; 239 const amount = result.session.amount; 240 const currency = result.session.currency; 241 242 loadExternalModule(result.javascript, () => { 243 epay 244 .setSessionId(sessionId) 245 .setSessionKey(sessionKey) 246 .setCallbacks({ 247 clientReady: clientReadyCallback, 248 invalidSession: invalidSessionCallback, 249 challengeIssued: challengeIssuedCallback, 250 transactionAccepted: transactionAcceptedCallback, 251 transactionDeclined: transactionDeclinedCallback, 252 clientRedirect: clientRedirectCallback, 253 invalidInput: invalidInputCallback, 254 inputValidity: inputValidityCallback, 255 inputSubmit: inputSubmitCallback, 256 sessionExpired: sessionExpiredCallback, 257 error: errorCallback, 258 }) 259 .init(); 260 261 epay.mountFields("fields", { 262 // The configuration object can be added here when needed. 263 }); 264 265 createPaymentButton(amount, currency); 266 }); 267 }) 268 .catch((error) => { 269 console.error("Error during payment request:", error); 270 displayError("Error during payment request", error); 271 });
Make your first test payment
in just a few minutes.
Try ePay for free and get started right away.
How to get started