Skip to main content

Hands-On Example: Build a Working Prototype in 10 min

If you just want to get something working quickly and understand how the integration flows, follow these 10 steps to implement a minimal Ealyx integration. This guide assumes you're integrating Ealyx Pay. If you're using Other Payment Methods instead, skip from Step 6 directly to Step 9.

Prerequisites

  • Sandbox credentials from Ealyx (CLIENT_ID, CLIENT_SECRET, USERNAME, PASSWORD)
  • curl installed on your system
  • A basic backend endpoint that can handle HTTP requests
  • jq installed (for JSON parsing in examples)

Integration Steps

Step 1: Set Your Credentials

Create a file: ealyx-config.sh

export CLIENT_ID="your_client_id_here"
export CLIENT_SECRET="your_client_secret_here"
export USERNAME="your_username_here"
export PASSWORD="your_password_here"
export API_BASE_URL="https://api.stg.ealyx.tech"
export ASSETS_URL="https://cdn.stg.ealyx.tech"

Load the config

source ealyx-config.sh

Step 2: Authenticate and Get Tokens

# Authenticate
BASIC_AUTH=$(echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64 | tr -d '\n')

AUTH_RESPONSE=$(curl -s -X POST "$API_BASE_URL/oauth2/token/" \
-H "Authorization: Basic $BASIC_AUTH" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=password' \
-d "username=$USERNAME" \
-d "password=$PASSWORD" \
-d "scope=core payments valuations")

# Extract tokens
export ACCESS_TOKEN=$(echo $AUTH_RESPONSE | jq -r '.access_token')
export REFRESH_TOKEN=$(echo $AUTH_RESPONSE | jq -r '.refresh_token')
export USER_ID=$(echo $AUTH_RESPONSE | jq -r '.user_id')
export MERCHANT_ID=$(echo $AUTH_RESPONSE | jq -r '.merchant_id')

echo "✓ Authentication successful"
echo "Access Token: ${ACCESS_TOKEN:0:20}..."
echo "User ID: $USER_ID"
echo "Merchant ID: $MERCHANT_ID"
✓ Verification
CheckExpectedIf it fails
ACCESS_TOKENNot nullCheck CLIENT_ID/SECRET are correct
USER_IDNot nullCheck USERNAME/PASSWORD are correct
MERCHANT_IDNot nullContact Ealyx - credentials may not be activated

Save these values: USER_ID and MERCHANT_ID are needed later for webhook signature validation.

Step 3: Add Teasers to Your Frontend

Add this to your HTML (before </body>):

<script>
window.ealyxConfiguration = {
merchantId: '{MERCHANT_ID}',
browserCallbackBase: '{MERCHANT_CALLBACKS_BASE}',
confirmUrl: '{MERCHANT_SUCCESS_URL}',
products: 'valuations+ep1' // Default is just 'valuations'
};
import('{ASSETS_URL}/v1/main.js')
.then(module => { window.Ealyx = module.Ealyx; })
.catch(err => console.error('Error loading Ealyx:', err));
</script>

<!-- Add teasers where you want them -->
<div class="ealyx-teaser" data-type="product-widget"></div>
✓ Verification

Open browser DevTools (F12) → Console tab:

CheckExpectedIf it fails
No errors in consoleClean loadCheck {ASSETS_URL} is correct
window.Ealyx existsObject with methodsSDK failed to load - check network tab
Teaser appearsWidget visible on pageCheck data-type attribute is valid

Step 4: Implement shopper_data Endpoint

Create a GET endpoint at $MERCHANT_CALLBACKS_BASE/shopper_data:

See Implement Shopper Data Endpoint for complete implementation details.

✓ Verification

Test your endpoint:

curl -X GET "$MERCHANT_CALLBACKS_BASE/shopper_data" \
-H 'Content-Type: application/json' \
-b 'session=YOUR_SESSION_COOKIE'

Expected response (when user is logged in):

{
"customer": {
"id": "customer_123",
"email": "john@example.com",
"given_name": "John",
"family_name": "Doe"
},
"session_hash_token": "abc123def456..."
}
CheckExpectedIf it fails
HTTP status200 OKCheck endpoint URL and method (must be GET)
customer objectPresent with id, email, namesEnsure user is logged in when testing
session_hash_tokenString (HMAC hash)Check your HMAC-SHA256 implementation

Step 5: Implement purchase_data Endpoint

Create a GET endpoint at $MERCHANT_CALLBACKS_BASE/purchase_data:

See Implement Purchase Data Endpoint for complete implementation details.

✓ Verification

Test your endpoint:

curl -X GET "$MERCHANT_CALLBACKS_BASE/purchase_data" \
-H 'Content-Type: application/json' \
-b 'session=YOUR_SESSION_COOKIE'

Expected response (when cart has items):

{
"purchase": {
"cart": {
"id": "cart_123",
"currency": "EUR",
"items": [{"id": "SKU1", "name": "Phone", "quantity": 1, "price": 10000, "tax": 2100, "total": 12100}],
"total": 12100
},
"billing": {"given_name": "John", "family_name": "Doe", "...": "..."},
"shipping": {"address": {"...": "..."}, "method": {"...": "..."}},
"customer": {"id": "customer_123", "email": "john@example.com"}
}
}
CheckExpectedIf it fails
HTTP status200 OKCheck endpoint URL and method (must be GET)
purchase.cart.itemsArray with cart itemsAdd items to cart before testing
All amounts are integers12100 not 121.00Multiply by 100 (values in cents)
Empty cart{"purchase": null}This is correct behavior

Step 6: Add Ealyx Pay Option to Checkout

First, call window.Ealyx?.paymentOptionDetailsFor('ep1') to determine how to display the Ealyx Pay option:

const details = window.Ealyx?.paymentOptionDetailsFor('ep1');
// Returns: { mode, template_name, label, info, extra?, data? }
modeMeaningAction
normalTrade-in ready for EP1Show as selectable payment method
popupNo valuation yetShow option that opens valuation wizard when selected
disableEP1 not availableShow as disabled with explanation

The response includes localized text fields:

  • label: Primary text for the payment method (e.g., "Pay €114.00 less with Ealyx Pay")
  • info: Explanatory text for info popups/tooltips
  • extra: Secondary text for expanded payment method details (optional)

Note: The label is plain text but the info and extra fields may contain HTML tags, like <br> for line breaks, <strong> for bold text, etc. They will never be long or complex.

In your checkout page HTML:

<label>
<input type="radio" name="payment_method" data-module-name="ealyx" value="ealyx_pay" />
<img src="img/ealyx-pay.svg" />
<span>{label}</span>
<span style="display: none;">{extra}</span>
<span style="display: none;">{info}</span>
</label>

If mode is popup, you need to open the valuation wizard (window.Ealyx.openValuation()) when the shopper tries to select the option. Refresh the payment option details when the valuation wizard is closed (listen for the ealyx-valuation-updated event), and select the Ealyx Pay option if and only if mode is normal.

Notes:

  • It is mandatory to include an EalyxPay icon somewhere in the payment option. It provides necessary context for some label texts.
  • The data-module-name="ealyx" attribute is used to identify the Ealyx Pay option to the SDK.
  • The info and extra fields start out hidden. The info field is designed to be displayed in a tooltip when the shopper hovers over the payment option or in a sidebar when the shopper clicks on an ℹ️ icon, and the extra field is designed to be displayed inline when the shopper selects the payment option. Neither field is mandatory, but most shops will want to use at least info.

Step 7: Add JavaScript Listeners for Ealyx Pay

// Show/hide Ealyx Pay option details
const paymentRadios = document.querySelectorAll('input[name="payment_method"]');
paymentRadios.forEach(radio => {
radio.addEventListener("change", () => {
const isEalyx = radio.value === "ealyx_pay";
window.Ealyx?.updatePaymentSelected(isEalyx);
});
});

// Intercept form submission to open Ealyx modal instead
document.querySelector("form").addEventListener("submit", function (e) {
const selected = document.querySelector('input[name="payment_method"]:checked');
const isEalyx = selected?.value === "ealyx_pay";

if (isEalyx) {
e.preventDefault();
window.Ealyx?.openPayment();
return false;
}
});
✓ Verification
CheckExpectedIf it fails
Ealyx Pay radio visibleShows in payment optionsCheck HTML is in checkout page
Selecting Ealyx PayNo JS errorsCheck window.Ealyx exists
Clicking "Place Order"Ealyx modal opensCheck form submit listener is attached
Modal shows discountTrade-in value visibleComplete valuation first (Steps 3-4)

Step 8: Implement Order Webhook (POST /order)

Create a POST endpoint at $MERCHANT_WEBHOOK_BASE/order:

See Handle Order Webhook for complete implementation details.

✓ Verification

Test signature validation locally:

SECRET="$USER_ID-$MERCHANT_ID"  # NOT CLIENT_SECRET!
BODY='{"data":{"cart_id":"cart_123","status":"pending"}}'
EXPECTED=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)
echo "Expected signature: $EXPECTED"
CheckExpectedIf it fails
Endpoint accessibleHTTP 200 (not 404)Check URL is publicly accessible
Signature matchesComputed = receivedSecret must be USER_ID-MERCHANT_ID, NOT CLIENT_SECRET
Response codeHTTP 200 exactlyEalyx requires 200 (not 201, 204, etc.)
Order createdRecord in databaseCheck your order creation logic

Step 9: Test the Flow

# 1. Visit your site and click "Calculate Discount"
# 2. Complete the valuation in the modal
# 3. Select "Pay with Ealyx" at checkout
# 4. Complete payment
# 5. Check your logs for webhook call
# 6. Verify order status in your database

echo "✓ Ealyx Pay integration complete!"

Step 10: Go to Production

Once testing is complete, request production credentials from your Ealyx account manager and update your configuration to use both the production endpoints and credentials:

export API_BASE_URL="https://api.ealyx.tech"
export ASSETS_URL="https://cdn.ealyx.tech"

# Use your production credentials
export CLIENT_ID="your_production_client_id"
export CLIENT_SECRET="your_production_client_secret"
export USERNAME="your_production_username"
export PASSWORD="your_production_password"