Fintech APIs & Platform for KYC, Verification & Transactions in India | Eko Platform ServicesPython SDK | Eko Platform Services
Eko Platform Services Logo
All SDKs

Python SDK

eps-sdk is a standard-library-only client for every EPS API. One generic call(slug, params) covers all of them: the endpoint catalog, each endpoint's params and which of them are required are baked into the package from the same surface these docs are built from, so the client validates your input before it signs and sends anything.

Warning

Backend only. access_key signs every request — it must never reach a browser, a mobile app, or a notebook you share.

Install

pip install eps-sdk
View eps-sdk on PyPI
Package
eps-sdk
Requires
Python 3.9 or newer
Dependencies
None — standard library only (urllib, hmac, hashlib, mimetypes).
Source
GitHub

Your first call

Read the two keys from the environment, pick an environment, and call an endpoint by its slug:

import os
from eps_sdk import EpsClient
client = EpsClient(
developer_key=os.environ["EPS_DEVELOPER_KEY"],
access_key=os.environ["EPS_ACCESS_KEY"],
initiator_id="9962981729",
environment="sandbox",
)
result = client.call("pan-lite", {
"pan_number": "ABCDE1234F",
"name": "Rajesh Kumar",
"dob": "1994-08-29",
})
print(result)

initiator_id and user_code are near-constant per developer, so set them once on the client. They are injected into every call — pass either in params to override it for a single call, or pass None to clear it.

Client options

EpsClient is a dataclass, so every option is a keyword argument.

OptionTypeRequiredNotes
developer_keystrYesYour EPS developer key, sent as the developer_key header.
access_keystrYesServer-side secret used to sign every request. Never ships to a browser.
environment"sandbox" | "production"YesSelects the base URL from the embedded surface.
initiator_idstrNoDefault initiator_id (registered mobile of the API user) injected into every call.
user_codestrNoDefault user_code (retailer/agent code) injected into every call.
timeoutfloatNoWhole-request budget passed through to urlopen. (seconds, default 30.0)

API surface

The SDK is deliberately small. There is no method per endpoint — call() takes the slug, and the baked surface supplies the method, path, and validation rules. resolve_target() is the same pipeline stopping one step short of the network, which is the fastest way to see exactly what would be sent.

MemberSignatureWhat it does
EpsClient
class
EpsClient(developer_key, access_key, environment, initiator_id=None, user_code=None, timeout=30.0)The client — a dataclass, so keyword arguments read well.
call
method
client.call(slug: str, params: Mapping[str, Any] | None = None) -> AnyValidates, signs and sends one endpoint call; returns the decoded envelope.
resolve_target
method
client.resolve_target(slug, params=None) -> TargetThe signed method/url/body/headers for a call, without sending it. Useful for debugging.
build_headers
method
client.build_headers(multipart: bool = False) -> dict[str, str]The four auth headers for a single request.
sign_secret_key
function
sign_secret_key(access_key: str, timestamp: str) -> strThe raw signing primitive, exported for debugging.
MULTIPART_JSON_FIELD
constant
MULTIPART_JSON_FIELD = "form-data"Name of the single form field carrying the JSON envelope on file-upload endpoints.
Target
type
@dataclass Target(method, url, body, headers, multipart)What resolve_target returns.

Authentication

You never compute a signature yourself. On every request the client derives secret-key = base64(HMAC-SHA256(timestamp, base64(access_key))) and sends it with secret-key-timestamp and developer_key. sign_secret_key is exported only so you can reproduce a signature while debugging a 403.

File uploads

A single type: "file" param flips the whole request to multipart/form-data. You still pass every parameter flat; on the wire the SDK packs them the way the API expects — one form field named form-data holding all the non-file params as a single JSON object, plus one part per upload. A None param is dropped (a form field has no null encoding), while a None nested inside a dict value is preserved.

File params accept:

  • A path str or os.PathLike (the MIME type is guessed, falling back to application/octet-stream)
  • An in-memory (filename, bytes) tuple

Errors and timeouts

A non-2xx response raises — an auth or infrastructure failure is never returned as if it were a result. The decoded envelope is still on the exception, so you can read status and message off .body.

TypeRaised whenFields
EpsHttpErrorAny non-2xx response..status, .url, .body (decoded envelope or None), .raw (bytes)
EpsErrorUnknown slug, missing required param, wrong param type, bad config, or a 2xx body that is not JSON. EpsHttpError subclasses it.
urllib.error.URLErrorTransport failure or timeout. Surfaced raw.
HTTP statusMeaning
200OK — response returned by our system.
403Forbidden — incorrect secret-key or timestamp.
404Not Found — wrong request URL.
405Method Not Allowed — incorrect HTTP method.
415Unsupported Media Type — wrong Content-Type header.
500Internal Server Error — connectivity or URL misconfiguration.

Environments

Switch with the environment argument; there is no base-URL override.

EnvironmentBase URLNotes
sandbox
UAT / Sandbox
https://staging.eko.in/ekoapi/v3Self-serve credentials available immediately on signup.
production
Production
https://api.eko.in/ekoicici/v3Credentials issued after organizational KYC.

Python-specific notes

  • Paths are checked for existence during validation, so a typo fails before the request is signed.

Every endpoint

call() accepts every slug in the EPS catalog. Each endpoint's reference page shows its parameters, response fields and a ready-to-paste Python snippet.

Browse the API reference
Next SDKPHP SDK