Nuvei REST API v1.0 SDK for Python — payment processing, 3D Secure, subscriptions, and more.
Project description
Nuvei Python SDK
A lightweight Python wrapper for the Nuvei REST API v1.0 — authentication, payments, 3D Secure, financial operations, subscriptions, user & payment option management, all in one package.
Requires Python 3.9+
Quick Links
- Features · Installation · Quick Start · Service Modules
- Integration Flows · Webhook Verification · Configuration
- Error Handling · Testing & Development · Helpful Resources
- Contributing · Changelog · License
Features
- Full API v1.0 coverage — authentication, payments, financial operations, 3D Secure, card operations, subscriptions, user & UPO management, advanced APM
- Sync and async clients — powered by
httpx - Automatic checksum calculation — SHA-256 (default) or MD5
- Webhook/DMN verification — validate
advanceResponseChecksumon incoming notifications - Type-annotated — full type hints with
py.typedmarker (PEP 561) - Minimal dependencies — only
httpx
Installation
pip install nuvei
Or for development:
pip install -e ".[dev]"
Quick Start
Synchronous Usage
from nuvei import Nuvei
client = Nuvei(
merchant_id="your_merchant_id",
merchant_site_id="your_site_id",
merchant_secret_key="your_secret_key",
environment="test", # "prod", "test", "int", "qa"
)
# 1. Get a session token
session = client.get_session_token()
token = session["sessionToken"]
# 2. Open an order
order = client.open_order(amount="10.00", currency="USD")
order_token = order["sessionToken"]
# 3. Process a payment
result = client.payments.payment(
sessionToken=order_token,
amount="10.00",
currency="USD",
paymentOption={
"card": {
"cardNumber": "4111111111111111",
"cardHolderName": "John Doe",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
)
print(result["transactionId"], result["status"])
Async Usage
import asyncio
from nuvei import AsyncNuvei
async def main():
async with AsyncNuvei(
merchant_id="your_merchant_id",
merchant_site_id="your_site_id",
merchant_secret_key="your_secret_key",
environment="test",
) as client:
session = await client.get_session_token()
print(session["sessionToken"])
asyncio.run(main())
Service Modules
Access API endpoints through organized service namespaces:
| Service | Accessor | Endpoints |
|---|---|---|
| Authentication | client.authentication |
get_session_token |
| Orders | client.orders |
open_order, update_order, get_order_details |
| Payments | client.payments |
payment, payment_cc, payment_apm, init_payment, get_payment_status, account_capture, get_mcp_rates, get_dcc_details |
| Financial | client.financial |
settle_transaction, refund_transaction, void_transaction, payout, get_payout_status |
| 3D Secure | client.three_d_secure |
authorize3d, verify3d, dynamic3d |
| Card Operations | client.card_operations |
card_tokenization, get_card_details |
| Users | client.users |
create_user, update_user, get_user_details |
| UPOs | client.user_payment_options |
add_upo_credit_card, add_upo_credit_card_by_temp_token, add_upo_credit_card_by_token, add_upo_apm, edit_upo_cc, edit_upo_apm, get_user_upos, delete_upo, suspend_upo, enable_upo, get_merchant_payment_methods |
| Subscriptions | client.subscriptions |
create_plan, edit_plan, get_plans_list, create_subscription, edit_subscription, cancel_subscription, get_subscriptions_list, get_subscription_plans |
| Advanced APM | client.advanced_apm |
add_bank_account, enroll_account, fund_account, get_account_details, get_document_url |
Integration Flows
Flow 1: Simple Payment (Sale)
The most common flow — charge a customer immediately.
from nuvei import Nuvei
client = Nuvei(
merchant_id="...", merchant_site_id="...",
merchant_secret_key="...", environment="test",
)
# Step 1: Open an order
order = client.open_order(amount="29.99", currency="USD")
# Step 2: Process the payment
result = client.payments.payment(
sessionToken=order["sessionToken"],
amount="29.99",
currency="USD",
transactionType="Sale",
paymentOption={
"card": {
"cardNumber": "4111111111111111",
"cardHolderName": "Jane Smith",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
deviceDetails={"ipAddress": "192.168.1.1"},
)
if result["status"] == "SUCCESS" and result["transactionStatus"] == "APPROVED":
print(f"Payment approved! Transaction ID: {result['transactionId']}")
Flow 2: Auth and Settle
Authorize first, then settle (capture) later — common for e-commerce.
# Step 1: Open order
order = client.open_order(amount="100.00", currency="USD")
# Step 2: Authorize (hold funds, don't charge yet)
auth = client.payments.payment(
sessionToken=order["sessionToken"],
amount="100.00",
currency="USD",
transactionType="Auth",
paymentOption={
"card": {
"cardNumber": "4111111111111111",
"cardHolderName": "John Doe",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
)
# Step 3: Settle (capture) — can be full or partial amount
settle = client.financial.settle_transaction(
relatedTransactionId=auth["transactionId"],
amount="100.00", # or a partial amount like "50.00"
currency="USD",
authCode=auth["authCode"],
)
Flow 3: Payment with 3D Secure (3DS 2.0)
Full 3DS flow for liability-shifted payments.
# Step 1: Open order
order = client.open_order(amount="50.00", currency="USD")
# Step 2: Init payment — check 3DS support
init = client.payments.init_payment(
sessionToken=order["sessionToken"],
amount="50.00",
currency="USD",
paymentOption={
"card": {
"cardNumber": "4000027891380961", # 3DS test card
"cardHolderName": "CL-BRW1",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
"threeD": {
"methodNotificationUrl": "https://your-site.com/3ds-notify",
},
}
},
)
# Step 3: Handle 3DS fingerprinting (client-side iframe)
# Render the threeD data from init["paymentOption"]["card"]["threeD"]
# Step 4: Authorize 3D (after challenge completion)
auth3d = client.three_d_secure.authorize3d(
sessionToken=order["sessionToken"],
amount="50.00",
currency="USD",
paymentOption={
"card": {
"threeD": {
# Include challenge result data here
}
}
},
relatedTransactionId=init["transactionId"],
)
# Step 5: Final payment with liability shift
payment = client.payments.payment(
sessionToken=order["sessionToken"],
amount="50.00",
currency="USD",
transactionType="Sale",
relatedTransactionId=auth3d["transactionId"],
paymentOption={
"card": {
"cardNumber": "4000027891380961",
"cardHolderName": "CL-BRW1",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
)
Flow 4: Returning Customer (CIT / MIT with UPO)
Save a payment method after the first transaction, then use it for future payments.
# --- First-time payment: Customer-Initiated Transaction (CIT) ---
# Step 1: Create the user
client.users.create_user(
userTokenId="customer_12345",
countryCode="US",
firstName="Jane",
lastName="Smith",
email="jane@example.com",
)
# Step 2: Open order with userTokenId
order = client.open_order(
amount="49.99", currency="USD",
userTokenId="customer_12345",
)
# Step 3: Process first payment (card is saved automatically with userTokenId)
first_payment = client.payments.payment(
sessionToken=order["sessionToken"],
amount="49.99",
currency="USD",
transactionType="Sale",
userTokenId="customer_12345",
paymentOption={
"card": {
"cardNumber": "4111111111111111",
"cardHolderName": "Jane Smith",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
)
# Step 4: Get saved payment methods (UPOs)
upos = client.user_payment_options.get_user_upos(
userTokenId="customer_12345",
)
upo_id = upos["paymentMethods"][0]["userPaymentOptionId"]
# --- Future payment: Use saved UPO (CIT or MIT) ---
order2 = client.open_order(
amount="49.99", currency="USD",
userTokenId="customer_12345",
)
future_payment = client.payments.payment(
sessionToken=order2["sessionToken"],
amount="49.99",
currency="USD",
transactionType="Sale",
userTokenId="customer_12345",
paymentOption={"userPaymentOptionId": upo_id},
isRebilling="0", # "1" for MIT (merchant-initiated)
)
Flow 5: Subscription / Rebilling
Set up automatic recurring payments.
# Step 1: Create a plan
plan = client.subscriptions.create_plan(
name="Premium Monthly",
initialAmount="0.00",
recurringAmount="29.99",
currency="USD",
endAfter={"day": "0", "month": "12", "year": "0"},
startAfter={"day": "0", "month": "1", "year": "0"},
)
# Step 2: Create a subscription for the user
sub = client.subscriptions.create_subscription(
userTokenId="customer_12345",
planId=plan["planId"],
userPaymentOptionId=upo_id,
initialAmount="0.00",
recurringAmount="29.99",
currency="USD",
endAfter={"day": "0", "month": "12", "year": "0"},
)
# Step 3: List active subscriptions
subs = client.subscriptions.get_subscriptions_list(
userTokenId="customer_12345",
subscriptionStatus="ACTIVE",
)
# Step 4: Cancel when needed
client.subscriptions.cancel_subscription(
subscriptionId=sub["subscriptionId"],
)
Flow 6: Refund
# Full refund
refund = client.financial.refund_transaction(
relatedTransactionId="original_txn_id",
amount="49.99",
currency="USD",
clientUniqueId="refund-001",
authCode="original_auth_code",
)
# Partial refund
partial_refund = client.financial.refund_transaction(
relatedTransactionId="original_txn_id",
amount="10.00", # partial amount
currency="USD",
clientUniqueId="refund-002",
authCode="original_auth_code",
)
Flow 7: Void
Cancel a transaction before settlement.
void = client.financial.void_transaction(
relatedTransactionId="original_txn_id",
amount="49.99",
currency="USD",
authCode="original_auth_code",
)
Flow 8: Payout
Send money to a payment method (credit/disbursement).
payout = client.financial.payout(
userTokenId="customer_12345",
amount="100.00",
currency="USD",
userPaymentOption={"userPaymentOptionId": upo_id},
comment="Withdrawal payout",
)
# Check payout status
status = client.financial.get_payout_status(
clientRequestId=payout["clientRequestId"],
)
Webhook (DMN) Verification
Nuvei sends Direct Merchant Notifications (DMN) to your server after transaction events. Always verify the checksum.
from nuvei import verify_webhook
# In your webhook handler (Flask, FastAPI, Django, etc.)
def handle_nuvei_webhook(params: dict):
is_valid = verify_webhook(
params,
merchant_secret_key="your_secret_key",
raise_on_failure=False, # or True to raise ChecksumError
)
if is_valid:
txn_id = params.get("PPP_TransactionID")
status = params.get("Status")
# Process the notification...
For custom DMN types with different field orderings:
from nuvei import verify_webhook_generic
verify_webhook_generic(
params,
merchant_secret_key="your_secret_key",
checksum_fields=["fieldA", "fieldB", "fieldC"],
checksum_param="advanceResponseChecksum",
secret_position="prefix", # or "suffix"
)
Configuration
Hash Algorithm
# Default is SHA-256; switch to MD5 if your account requires it
client = Nuvei(..., algorithm="md5")
Environments
| Environment | Base URL |
|---|---|
prod |
https://secure.safecharge.com |
test |
https://ppp-test.nuvei.com |
int |
https://ppp-test.nuvei.com |
qa |
https://apmtest.gate2shop.com |
Context Manager
# Auto-close the HTTP client
with Nuvei(...) as client:
session = client.get_session_token()
Error Handling
The SDK raises specific exceptions for different failure modes:
from nuvei import APIError, AuthenticationError, TransportError, ChecksumError
try:
result = client.payments.payment(...)
except AuthenticationError as e:
# Session token or credential issues
print(f"Auth failed: {e.reason}")
except APIError as e:
# Nuvei API returned an error
print(f"API error {e.err_code}: {e.reason}")
print(e.response_body) # full response dict
except TransportError as e:
# Network / HTTP-level errors
print(f"Network error: {e}")
Response Handling
Every API method returns the full response dict from Nuvei. Check these fields:
| Field | Description |
|---|---|
status |
"SUCCESS" or "ERROR" — indicates if the request was processed |
errCode |
0 for success, non-zero for errors |
reason |
Human-readable error description |
transactionStatus |
"APPROVED", "DECLINED", "PENDING", "ERROR" — actual transaction result |
transactionId |
Nuvei's unique transaction identifier |
authCode |
Authorization code from the issuer |
gwErrorCode |
Gateway-specific error code |
gwErrorReason |
Gateway-specific error description |
Important: A
status: "SUCCESS"means the request was processed — it does NOT mean the transaction was approved. Always checktransactionStatusfor the actual result.
For more details, see: Nuvei Response Handling Guide
Testing & Development
Running Tests
pip install -e ".[dev]"
python -m pytest tests/ -v
Testing Cards
Use these test card numbers in the test environment:
| Card Number | Brand | Behavior |
|---|---|---|
4111111111111111 |
Visa | Approved |
5111111111111118 |
Mastercard | Approved |
4000027891380961 |
Visa | 3DS Challenge |
4000020951595032 |
Visa | 3DS Frictionless |
4000023104662535 |
Visa | Declined |
- Expiry date: Any future date (e.g.
12/2028) - CVV: Any 3 digits (e.g.
217)
For the full list of testing cards, see: Nuvei Testing Cards
Testing with Postman
Nuvei provides a Postman collection for testing API calls interactively:
- Import the Nuvei API collection into Postman
- Set environment variables:
merchantId,merchantSiteId,merchantSecretKey - Use the collection to test individual endpoints and verify responses
For details, see: Testing APIs with Postman
Helpful Resources
| Resource | Link |
|---|---|
| Nuvei API v1.0 Reference | Main API Docs |
| Advanced API Reference | Advanced API Docs |
| Response Handling | Response Handling Guide |
| Webhooks (DMN) | Webhook Documentation |
| Testing Cards | Testing Cards Reference |
| Testing with Postman | Postman Guide |
| 3D Secure | 3DS Documentation |
| Financial Operations | Financial Ops Guide |
| Subscription/Rebilling | Subscription Docs |
| Authentication | Auth Documentation |
| Checksum Tool | Online Checksum Calculator |
Contributing
Contributions are welcome! If you find a bug, have a feature request, or want to improve the SDK:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes and add tests
- Open a pull request
For bugs or questions, open an issue.
Changelog
See CHANGELOG.md for a full list of changes in each release.
License
MIT — see LICENSE for details.
Made with Python & ❤️ by KK Jangid
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nuvei-1.0.2.tar.gz.
File metadata
- Download URL: nuvei-1.0.2.tar.gz
- Upload date:
- Size: 37.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbcf2cff139c2c47a35741f54e9a045cf66fb9cfa49d74efba0f15707680bded
|
|
| MD5 |
98e911de6d2e993508ed644b4d207565
|
|
| BLAKE2b-256 |
45583b1c85c82b2339e9ce1eb2de2bbca0227548d27dbf899cdd1942a1460616
|
Provenance
The following attestation bundles were made for nuvei-1.0.2.tar.gz:
Publisher:
publish.yml on krishanjangid/nuvei-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nuvei-1.0.2.tar.gz -
Subject digest:
bbcf2cff139c2c47a35741f54e9a045cf66fb9cfa49d74efba0f15707680bded - Sigstore transparency entry: 1090996103
- Sigstore integration time:
-
Permalink:
krishanjangid/nuvei-python@b7c807bbeca1dec5133d2d967fe41ad6d82d482d -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/krishanjangid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b7c807bbeca1dec5133d2d967fe41ad6d82d482d -
Trigger Event:
release
-
Statement type:
File details
Details for the file nuvei-1.0.2-py3-none-any.whl.
File metadata
- Download URL: nuvei-1.0.2-py3-none-any.whl
- Upload date:
- Size: 28.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
edb421acf383235520ad303a5e47eace6b1f8657b725307f4a0491621955da48
|
|
| MD5 |
b0ffaa10275a42052a678fcd7c49e033
|
|
| BLAKE2b-256 |
18e5c6eab766229a4d4d34453bcbb23b6bf71201f83f56d7111b07a2b029392e
|
Provenance
The following attestation bundles were made for nuvei-1.0.2-py3-none-any.whl:
Publisher:
publish.yml on krishanjangid/nuvei-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nuvei-1.0.2-py3-none-any.whl -
Subject digest:
edb421acf383235520ad303a5e47eace6b1f8657b725307f4a0491621955da48 - Sigstore transparency entry: 1090996122
- Sigstore integration time:
-
Permalink:
krishanjangid/nuvei-python@b7c807bbeca1dec5133d2d967fe41ad6d82d482d -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/krishanjangid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b7c807bbeca1dec5133d2d967fe41ad6d82d482d -
Trigger Event:
release
-
Statement type: