The Python SDK (lyel-pay) is designed for server-side environments. Use it from Django, Flask, FastAPI, Odoo, or any Python backend to create payment intents, retrieve their status, and validate incoming webhook events.
Installation
Requires Python 3.9 or later. Depends on httpx.
Initialization
The simplest setup reads the secret key from the LYEL_PAY_SECRET_KEY environment variable and points at sandbox while you build:
Or pass the key explicitly:
| Parameter | Type | Required | Description |
|---|
secret_key | str | ✅* | Secret API key. Falls back to LYEL_PAY_SECRET_KEY env var if omitted. |
environment | str | ❌ | "sandbox" or "production". Defaults to "production". |
base_url | str | ❌ | Override the API base URL. Useful for staging. |
timeout | float | ❌ | Per-request timeout in seconds. Defaults to 30.0. |
Constructing the client without a key and without the environment variable
raises ValueError. Always configure one or the other.
Payment Intents
client.payment_intents.create(...)
Create a payment intent from your backend before showing the checkout to the customer.
Parameters:
| Field | Type | Required | Description |
|---|
amount | str | ✅ | Amount as a decimal string (e.g. "1500.00"). |
currency | str | ✅ | ISO 4217 currency code: XAF, XOF, CDF, EUR, USD. |
description | str | ❌ | Human-readable description. |
metadata | dict | ❌ | Custom key/value pairs. Returned on webhook events. |
idempotency_key | str | ❌ | Safe-retry token. Auto-generated as a UUID4 if omitted. |
Pass an explicit idempotency_key derived from a stable identifier (e.g. your
order ID) when the same logical operation may be retried — the API will
deduplicate so you never create a second intent for the same order.
client.payment_intents.retrieve(session_token)
Retrieve the current status of an intent using its session token.
Use retrieve() only as a fallback. For production, webhooks are the
authoritative source of truth — they keep state correct even when the
customer closes their browser mid-payment.
Webhooks
Validates an incoming webhook event and returns the parsed event. Raises ValueError if the signature is invalid or the timestamp is older than 5 minutes.
Use the raw request body (e.g. request.get_data() in Flask, request.body
in Django, await request.body() in FastAPI). Re-serializing the parsed JSON
changes the byte order and breaks the HMAC check.
Signature format: the Lyel-Signature header carries
t — Unix timestamp at emission
v1 — HMAC-SHA256 of "{t}.{payload}", keyed by your webhook secret
Webhook event types:
| Type | Description |
|---|
payment.completed | Payment was successfully processed |
payment.failed | Payment attempt failed |
payment.expired | Intent expired before completion |
Error handling
API errors raise LyelPayError, which carries the HTTP status code:
The SDK retries automatically on 5xx responses and network errors — 3 attempts with exponential backoff (1s, 2s). 4xx errors are surfaced immediately without retry, because they will not succeed on retry.
Full example: Django checkout
Source & changelog