Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
payrix
A Rust client library for the Payrix payment processing API.
This library was created based on 18 months of production experience implementing Payrix Pro, documenting quirks and API inconsistencies along the way. We used Claude Code to help with grunt work like ensuring enum correctness and documenting return codes.
Features
- Full async/await support with Tokio
- Built-in rate limiting to avoid API throttling
- Automatic retry with exponential backoff for transient failures
- Strongly typed API responses with 86 enums and 73 resource types
- High-level workflows for complex multi-step operations
- Comprehensive error handling with domain-specific error types
- Optional SQLx support for database integration
- Webhook server for receiving real-time event notifications
- OpenAPI 3.1 spec included for reference
Installation
Add this to your Cargo.toml:
[]
= "0.1"
= { = "1", = ["rt-multi-thread", "macros"] }
Feature Flags
# Enable SQLx derive macros for database storage
= { = "0.1", = ["sqlx"] }
# Enable webhook server for receiving Payrix callbacks
= { = "0.1", = ["webhooks"] }
# Enable local entity cache for faster queries
= { = "0.1", = ["cache"] }
# Enable all optional types (financial reports, terminals)
= { = "0.1", = ["full"] }
# Enable CLI binary for entity lookups and operations
= { = "0.1", = ["cli"] }
| Feature | Description |
|---|---|
sqlx |
SQLx FromRow derives for database storage |
webhooks |
Webhook server for receiving Payrix callbacks |
webhook-cli |
CLI binary for webhook server management |
cache |
Local entity cache for faster queries |
financial |
Financial/reporting types (settlements, statements) |
terminal |
Terminal/physical device types |
cli |
CLI binary for entity lookups and operations |
full |
All optional types (financial + terminal) |
Quick Start
use ;
async
Common Operations
Creating a Transaction
use ;
async
Searching for Records
use ;
async
Search Operators
The library provides strongly-typed search operators. These have been tested against the live API:
| Operator | String | Description | Example |
|---|---|---|---|
Equals |
equals |
Exact match (default) | inactive[equals]=0 |
Exact |
exact |
Exact string match | name[exact]=Test Plan |
Greater |
greater |
Greater than (>) | amount[greater]=1000 |
Less |
less |
Less than (<) | amount[less]=5000 |
Like |
like |
Pattern match (% wildcard) | name[like]=%test% |
In |
in |
Value in list | status[in]=1,2,3 |
NotIn |
notin |
Value NOT in list | status[notin]=0 |
Diff |
diff |
Not equal (!=) | inactive[diff]=1 |
NotLike |
notlike |
Pattern NOT matching | name[notlike]=%test% |
Sort |
sort |
Sort results | created[sort]=desc |
Warning: The operators
gte,lte,gt,lt,lesser, andeqare documented in Payrix but do NOT work (they return empty results). Always usegreaterandlessinstead.
Basic Operator Usage
use ;
// Greater than: find plans with amount > $10.00
let search = new
.field_with_op
.build;
// Produces: "amount[greater]=1000"
// Less than: find plans with amount < $100.00
let search = new
.field_with_op
.build;
// Produces: "amount[less]=10000"
// Pattern matching: find customers with email containing "gmail"
let search = new
.field_with_op
.build;
// Produces: "email[like]=%gmail%"
// Multiple values: find transactions with status 1, 2, or 3
let search = new
.field_multi
.build;
// Produces: "status[in]=1,2,3"
Combining Conditions (AND)
Multiple conditions are combined with AND logic by default:
use ;
// Find active plans with amount > $10.00
let search = new
.field
.field_with_op
.build;
// Produces: "inactive[equals]=0&amount[greater]=1000"
OR Conditions
Use or_group() for OR logic:
use ;
// Find plans where status=1 OR status=2
let search = new
.or_group
.build;
// Produces: "[or]status[equals]=1&[or]status[equals]=2"
// Complex: (inactive=0 OR inactive=1) AND amount > 0
let search = new
.or_group
.field_with_op
.build;
// Produces: "[or]inactive[equals]=0&[or]inactive[equals]=1&amount[greater]=0"
Date Range Queries
Dates must be in YYYYMMDD format (no dashes):
use ;
use make_payrix_date;
use NaiveDate;
// Find transactions created in December 2025
let start = from_ymd_opt.unwrap;
let end = from_ymd_opt.unwrap;
let search = new
.field_with_op
.field_with_op
.build;
// Produces: "created[greater]=20251201&created[less]=20251231"
Sorting Results
use ;
// Sort by created date descending (newest first)
let search = new
.field
.field_with_op
.build;
// Produces: "inactive[equals]=0&created[sort]=desc"
Pagination
use ;
async
Expanding Related Resources
use ;
async
High-Level Workflows
The library includes workflow modules that encapsulate complex multi-step operations:
| Workflow | Description |
|---|---|
merchant_onboarding |
Onboard new merchants with business info, bank accounts, and owners |
dispute_handling |
Handle chargeback disputes with compile-time state enforcement |
webhook_setup |
Set up webhook alerts for real-time event notifications |
subscription_management |
Manage customer subscriptions to recurring payment plans |
payment_processing |
Process credit card and bank account payments |
customer_management |
Create and manage customers with address matching |
tokenization |
Tokenize payment methods with automatic customer creation |
transaction_management |
Handle refunds, voids, and transaction lookups |
hold_handling |
Handle transaction holds from risk department with compile-time state enforcement |
account_management |
Manage entities, merchants, bank accounts, and funds |
Merchant Onboarding
use ;
use ;
use ;
async
Dispute Handling (Type-State Pattern)
The dispute handling workflow uses Rust's type system to enforce valid state transitions at compile time:
use ;
use ;
async
Hold Handling (Type-State Pattern)
The hold handling workflow uses Rust's type system to enforce valid state transitions at compile time:
use PayrixClient;
use Hold;
use ;
async
Webhook Setup
use ;
async
API Coverage
| Category | Resources |
|---|---|
| Core | Merchants, Entities, Customers, Tokens, Transactions, TxnRefs |
| Banking | Accounts, AccountVerifications, Funds, Disbursements |
| Billing | Subscriptions, Plans, Fees, FeeRules |
| Operations | Batches, Payouts, Reserves, Adjustments, PinlessDebitConversions |
| Disputes | Chargebacks, ChargebackMessages, ChargebackDocuments |
| Admin | Orgs, TeamLogins, Members, Contacts, Vendors |
Environment Configuration
Payrix provides separate test (sandbox) and production environments. Each requires its own API key.
use ;
// Test environment (sandbox) - for development and integration testing
let test_client = new?;
// Production environment - for live transactions
let prod_client = new?;
| Environment | Base URL | ID Prefix |
|---|---|---|
| Test | https://test-api.payrix.com/ |
t1_ |
| Production | https://api.payrix.com/ |
p1_ |
Selecting the Environment at Runtime
A common pattern is to select the environment based on configuration:
use ;
use env;
Environment Differences
Some API endpoints behave differently between environments:
- Payouts are not processed in the test environment (
/payoutsreturns empty results) - Chargebacks cannot be moved through the full lifecycle in test mode
- Merchant boarding works in test mode but underwriting approval requires Payrix support
- Some newer endpoints (e.g.,
/txnRefs,/valueAddedServices/pinlessDebitConversions) may require elevated API key permissions in either environment
Error Handling
use ;
async
Design Decisions
Rate Limiting Strategy
The client implements two-layer rate limiting:
- Proactive - Tracks outgoing requests with a sliding window to stay under API limits
- Reactive - Handles 429 responses with exponential backoff (10s sleep, up to 3 retries)
Why Not Tower Middleware?
This library uses method-specific helpers instead of Tower middleware:
- Simplicity - Tower's trait bounds add complexity without proportional benefit
- Payrix quirks - Payrix returns HTTP 200 with errors in the JSON body
- Debuggability - Simple loops are easier to trace than middleware stacks
- Code size - ~50 lines for retry+rate limiting vs 100+ for Tower setup
Reality Wins
When the OpenAPI spec differs from actual API behavior, we follow reality:
- Flexible deserializers - Transaction enums accept both integer and string formats
- Undocumented variants - Added enum values observed in production
- Optional fields - Made fields like
Customer.merchantoptional when API returns null - Integer vs string enums -
FeeType,FeeUnit,FeeCollectionuse integers
See API_INCONSISTENCIES.md for the full catalog of discrepancies.
Testing
| Category | Count | Status |
|---|---|---|
| Unit tests | 685 | All passing |
| Doc tests | 53 | All passing |
| Integration tests | 380+ | Ignored (require API key) |
Running Tests
# Unit and doc tests (no API key required)
# Integration tests against test (sandbox) environment
TEST_PAYRIX_API_KEY=your_test_key
# Integration tests against production (GET-only, read-safe)
PAYRIX_PRODUCTION_API_KEY=your_prod_key
# Specific test suite
TEST_PAYRIX_API_KEY=your_test_key
Test Environment Variables
| Variable | Required | Description |
|---|---|---|
TEST_PAYRIX_API_KEY |
For sandbox tests | API key for the test/sandbox environment |
PAYRIX_PRODUCTION_API_KEY |
For production tests | API key for the production environment (GET-only tests) |
TEST_MERCHANT_ID |
No | Merchant ID for resource creation tests (default provided) |
TEST_ENTITY_ID |
No | Entity ID for entity tests (default provided) |
When both PAYRIX_PRODUCTION_API_KEY and TEST_PAYRIX_API_KEY are set, tests that support both environments will prefer the production key. This is useful for verifying deserialization against real production data.
If your production key is stored under a different variable name, alias it when running tests:
# Alias an existing env var
PAYRIX_PRODUCTION_API_KEY=
API Reference
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Disclaimer
This is an unofficial client library. Payrix and Worldpay are trademarks of their respective owners.