Introduction
Base URLs, authentication, response format and the two calls of a checkout.
The Checkout API lets your server take payments with a one-time payment link. Your server logs in with your API key, then creates a link for the order. The customer opens the link and pays with any method; everything in between — choosing a method, the PIN prompt, the QR code — happens on the Zoorya Pay payment page. This page covers what every request needs: the base URL, the token, and the request and response format.
The two endpoints:
| Method | Path | Purpose |
|---|---|---|
POST | /authentication/login | Log in with your API key and get a token |
POST | /tenants/{tenantId}/organisations/{organisationId}/payments | Create a one-time link for an order |
To confirm the payment afterwards, call Get a payment.
Base URLs#
Use the base URL of the environment your API key belongs to. A sandbox key does not work on production, and the reverse.
| Environment | Base URL |
|---|---|
| Sandbox | https://sandbox.eclipse.et/eclipse-conductor/rest/v1 |
| Production | To be announced |
Authentication#
Every call except Log in needs a token. Send your API key to Log in and you get headerValue back. Send it as the Authorization header — it already starts with Bearer :
Authorization: Bearer eyJraWQiOiIxIiwiYWxnIjoiUFMyNTYifQ...The token works for about 15 minutes. Reuse it until then; after that, calls return 401 — log in again.
Get your API key in the merchant portal under Developer → API keys. See Get your API keys.
Requests#
Send JSON bodies with Content-Type: application/json.
Responses#
A successful call returns the object you asked for — for example the payment you created. A failed call returns a list of errors:
{
"paymentId": 4581646,
"status": "PENDING",
"completionUrl": "https://sandbox.eclipse.et/t/abc12"
}See Error codes for how to read them.
Redirect the customer and store the reference#
When Create a one-time link succeeds, the response has a completionUrl. That is the Zoorya Pay checkout page for this order. What to do with it:
- 1
Store the reference
Save
paymentIdand yourexternalUniqueIdwith the order in your database. You need them later to check the payment and to match the webhook to the order. - 2
Send the customer to completionUrl
On a website, redirect the browser to
completionUrl. In a chat, SMS or email, send it as a link. Send only the URL — the rest of the response contains your HMACKey and stays on your server. - 3
The customer pays on the checkout page
They pick a method (telebirr, M-Pesa, a bank…), approve the prompt on their phone, and are sent back to your
landingUrl. - 4
Confirm before you deliver
Coming back to
landingUrldoes not mean they paid. Wait for the webhook at yourcallbackUrl, or call Get a payment with the storedpaymentId. Deliver the order only whenstatusisSUCCESSFULand the amount and currency match the order.
app.post("/checkout", async (req, res) => {
const payment = await createPaymentLink(order); // your call to Create a one-time link
await db.orders.update(order.id, {
paymentId: payment.paymentId,
externalUniqueId: payment.externalUniqueId,
status: "PENDING",
});
res.redirect(303, payment.completionUrl); // send the customer to the checkout page
});Use completionUrl exactly as it comes back. Don't build the checkout URL yourself from a hardcoded host — the host differs between sandbox and production. Each link is for one order; create a new one for the next order.
Bored of the checkout thing already? 😴 Redirects, landing pages, "please wait while we load the payment page"… bla bla bla. Skip all of it: with C2B Direct your own app asks the customer how they pay, your server charges them directly, and they never leave your app. Same login, same webhook — just less walking around. 🚀

