Transactions

Retrieve a Transaction

Fetch the current status and details of a transaction using its ePay reference.

Retrieve a Transaction

GET /v1/transactions/:reference

Returns the current state of a transaction. Use this to poll for status updates or reconcile payments against your records.


Request

raw HTTP
npm install @e-pay/node
npm install @e-pay/nestjs
pip install epay
pip install epay
pip install epay
pip install epay
composer require epay-et/php-sdk
composer require epay-et/php-sdk
implementation("com.epayethiopia:epay-java:0.1.0")
implementation("com.epayethiopia:epay-spring-boot-starter:0.1.0")
go get github.com/epay-et/go-sdk

Nothing NestJS-specific here — this is the same Node.js client call.

Nothing Django-specific here — this is the same Python client call.

Nothing Flask-specific here — this is the same Python client call.

Nothing FastAPI-specific here — this is the same Python client call.

Nothing Laravel-specific here — this is the same PHP client call.

Nothing Spring Boot-specific here — this is the same Java client call.

curl https://api.epayethiopia.com/v1/transactions/PAB12CD3420260813 \
  -H "Authorization: Bearer sk_live_your_key_here"
import { Epay } from '@e-pay/node';

const epay = new Epay({ apiKey: process.env.EPAY_SECRET_KEY });

const transaction = await epay.transactions.retrieve(reference);

if (transaction.status === 'completed') {
const receipt = await epay.payments.verify(reference);
await fulfil(receipt);
}
const res = await fetch('https://api.epayethiopia.com/v1/transactions/PAB12CD3420260813', {
  headers: { Authorization: `Bearer ${process.env.EPAY_SECRET_KEY}` },
});

if (!res.ok) throw new Error(`ePay ${res.status}: ${await res.text()}`);

const transaction = await res.json();
from epay import Epay

epay = Epay() # reads EPAY_SECRET_KEY

transaction = epay.transactions.retrieve(reference)

if transaction["status"] == "completed":
receipt = epay.payments.verify(reference)
fulfil(receipt)
import os
import requests

res = requests.get(
    "https://api.epayethiopia.com/v1/transactions/PAB12CD3420260813",
    headers={"Authorization": f"Bearer {os.environ['EPAY_SECRET_KEY']}"},
    timeout=30,
)
res.raise_for_status()

transaction = res.json()
use Epay\Epay;

$epay = new Epay(); // reads EPAY_SECRET_KEY

$transaction = $epay->transactions->retrieve($reference);

if ($transaction['status'] === 'completed') {
    $receipt = $epay->payments->verify($reference);
fulfil($receipt);
}
$ch = curl_init('https://api.epayethiopia.com/v1/transactions/PAB12CD3420260813');

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('EPAY_SECRET_KEY')],
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException("ePay {$status}: {$body}");
}

$transaction = json_decode($body, true);
transaction, err := client.Transactions.Retrieve(ctx, reference)
if err != nil {
	return err
}

// Nullable fields are pointers, so "absent" stays distinct from "empty".
if transaction.PaidAt != nil {
log.Println("paid at", \*transaction.PaidAt)
}

if transaction.Status == epay.StatusCompleted {
receipt, err := client.Payments.Verify(ctx, reference)
if err != nil {
return err
}
return fulfil(receipt)
}
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.epayethiopia.com/v1/transactions/PAB12CD3420260813", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("EPAY_SECRET_KEY"))

res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()

if res.StatusCode >= 400 {
	return fmt.Errorf("ePay %d", res.StatusCode)
}

var transaction struct {
	Reference    string  `json:"reference"`
	Status       string  `json:"status"`
	Amount       string  `json:"amount"`
	CurrencyCode string  `json:"currencyCode"`
	PaidAt       *string `json:"paidAt"`
	CreatedAt    string  `json:"createdAt"`
}
if err := json.NewDecoder(res.Body).Decode(&transaction); err != nil {
	return err
}
Epay epay = Epay.fromEnvironment(); // reads EPAY_SECRET_KEY

Transaction transaction = epay.transactions().retrieve(reference);

// Nullable fields stay null, so "not paid yet" is distinct from anything else.
if (transaction.paidAt() != null) {
System.out.println("paid at " + transaction.paidAt());
}

if (transaction.status() == TransactionStatus.COMPLETED) {
VerifiedPayment receipt = epay.payments().verify(reference);
fulfil(receipt);
}
HttpClient http = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder(
                URI.create("https://api.epayethiopia.com/v1/transactions/PAB12CD3420260813"))
        .header("Authorization", "Bearer " + System.getenv("EPAY_SECRET_KEY"))
        .GET()
        .build();

HttpResponse<String> response = http.send(request, HttpResponse.BodyHandlers.ofString());

if (response.statusCode() >= 400) {
    throw new IllegalStateException("ePay " + response.statusCode() + ": " + response.body());
}

// Parse with Jackson, Gson, or your JSON library of choice.
String transaction = response.body();
import { Controller, Get, NotFoundException, Param } from '@nestjs/common';
import { EpayNotFoundError, EpayService } from '@e-pay/nestjs';

@Controller('payments')
export class PaymentsController {
constructor(private readonly epay: EpayService) {}

@Get(':reference')
async status(@Param('reference') reference: string) {
try {
return await this.epay.transactions.retrieve(reference);
} catch (error) {
if (error instanceof EpayNotFoundError) throw new NotFoundException();
throw error;
}
}
}
from django.http import Http404, JsonResponse
from django.views.decorators.http import require_GET
from epay import EpayNotFoundError

from .clients import epay  # Epay(api_key=settings.EPAY_SECRET_KEY)


@require_GET
def payment_status(request, reference):
    try:
        return JsonResponse(epay.transactions.retrieve(reference))
    except EpayNotFoundError:
        raise Http404
from flask import abort, jsonify
from epay import EpayNotFoundError

from app import app, epay # epay = Epay(), one per process

@app.get("/payments/<reference>")
def payment_status(reference):
try:
return jsonify(epay.transactions.retrieve(reference))
except EpayNotFoundError:
abort(404)
from fastapi import HTTPException
from epay import EpayNotFoundError

from app.main import app, epay  # epay = AsyncEpay(), closed in lifespan


@app.get("/payments/{reference}")
async def payment_status(reference: str):
    try:
        return await epay.transactions.retrieve(reference)
    except EpayNotFoundError:
        raise HTTPException(404)
use Epay\Epay;
use Epay\Exception\EpayNotFoundException;
use Illuminate\Http\JsonResponse;

final class PaymentController
{
public function \_\_construct(private readonly Epay $epay) {}

    public function show(string $reference): JsonResponse
    {
        try {
            return response()->json($this->epay->transactions->retrieve($reference));
        } catch (EpayNotFoundException) {
            abort(404);
        }
    }

}

// routes/web.php
// Route::get('/payments/{reference}', [PaymentController::class, 'show']);
@RestController
@RequestMapping("/payments")
class PaymentController {
    private final Epay epay;

    PaymentController(Epay epay) {
        this.epay = epay;
    }

    @GetMapping("/{reference}")
    Transaction status(@PathVariable String reference) {
        try {
            return epay.transactions().retrieve(reference);
        } catch (EpayNotFoundException e) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND);
        }
    }
}

Response

{
  "reference": "PAB12CD3420260813",
  "merchantReference": "order_123",
  "status": "completed",
  "amount": "250.00",
  "currencyCode": "ETB",
  "paidAt": "2026-08-13T11:47:00.000Z",
  "createdAt": "2026-08-13T11:30:00.000Z"
}

Path Parameters

Prop

Type


Response

Prop

Type


Transaction statuses

StatusDescription
pendingSession created; customer has not yet interacted with the checkout.
processingCustomer is actively on the checkout page.
completedPayment was successful.
failedPayment attempt failed.
cancelledTransaction was cancelled via the API or by the customer.

Errors

StatusDescription
401Missing or invalid API key.
404No transaction found for the given reference under your account.

Next: Transaction Timeline — see every event recorded against this transaction.

On this page