Pay-i Client APIs
Overview
The Pay-i Python SDK provides client classes (Payi
for synchronous, AsyncPayi
for asynchronous) that serve as your primary interface for interacting programmatically with the Pay-i API.
Use the Pay-i client when you need to:
- Automate Configuration Management: Create, update, or delete Pay-i entities like categories, resources, limits, and use cases directly from your code, often as part of deployment scripts or operational workflows.
- Submit Usage Data Manually: Send detailed event data (usage metrics, latency, metadata) to Pay-i using the
client.ingest
object. This is crucial for tracking custom resources, integrating non-Python applications, or backfilling historical data. See the Ingest API documentation for details. - Retrieve Specific Request Details: Fetch information about individual past requests processed by Pay-i using
client.requests
, useful for debugging or targeted analysis. Note that bulk data export is not a primary function of this client API; real-time event data like cost and limit status is typically obtained from thexproxy_result
during runtime operations. - Build Custom Tooling: Develop internal applications or scripts that leverage Pay-i's configuration and individual request data for specialized reporting, monitoring, or management tasks.
The client complements Pay-i's automated instrumentation by providing direct, programmatic control over your Pay-i setup and data submission.
Core Functionality: API Resource Objects
Once initialized (client = Payi()
or async_client = AsyncPayi()
), the client object grants access to different areas of the Pay-i API via dedicated resource properties. These properties align with the major functional areas documented in the Pay-i API Reference:
Property | Description | Key Use Cases | Documentation Link |
---|---|---|---|
client.ingest | Submit detailed event data (usage, latency, metadata) after an interaction. | Manual event submission, tracking custom resources, historical data backfill. | Ingest API |
client.categories | Manage AI model categories and the resources within them. | Exploring available models, creating/deleting custom resources, managing resource versions (pricing changes). | Categories & Resources |
client.limits | Create, retrieve, update, delete, and reset usage limits and budgets. | Programmatically managing budgets, setting spending caps, associating limits with requests. | [Link TBD] |
client.use_cases | Define, manage, and track specific application use cases. | Setting up use case tracking, managing use case versions, associating requests with use cases. | [Link TBD] |
client.requests | Retrieve details about specific past requests processed by Pay-i. | Fetching cost, latency, and metadata for individual requests, debugging specific interactions. | [Link TBD] |
client.experiences | Deprecated. Experience tracking and management. | Previously used for tracking user experiences; replaced by the more robust Use Cases system. | N/A |
Each property (e.g., client.limits
) returns an object providing methods for the corresponding API operations (e.g., client.limits.create()
, client.categories.list_resources()
).
Initialization and Configuration
Now that you understand the client's purpose and the resources it provides access to, let's cover setup.
Basic Initialization
For most applications, the simplest initialization is sufficient:
from payi import Payi
# Create a synchronous client
# API key automatically loaded from PAYI_API_KEY environment variable
client = Payi()
# Create an asynchronous client
# from payi import AsyncPayi
# async_client = AsyncPayi()
This default setup:
- Reads the API key from the
PAYI_API_KEY
environment variable. - Connects to the standard Pay-i API endpoint (
https://api.pay-i.com
). - Uses default network timeout and retry settings.
Configuration Options
You can customize the client's behavior during initialization. Pay-i strongly recommends using environment variables (PAYI_API_KEY
, PAYI_BASE_URL
) for configuring the API key and base URL, as shown in the table below, for better security and flexibility across environments.
Parameter | Description | Default | Environment Variable (Recommended) |
---|---|---|---|
api_key | Your Pay-i API key | Required (no default) | PAYI_API_KEY |
base_url | The Pay-i API endpoint URL | https://api.pay-i.com | PAYI_BASE_URL |
timeout | Request timeout (float or Timeout object) | 60 seconds (request), 5 seconds (connect) | - |
max_retries | Maximum retry attempts on transient errors | 2 | - |
default_headers | Custom headers to include in all requests | None | - |
default_query | Custom query parameters to include in all requests | None | - |
http_client | Custom httpx client instance | Auto-created based on sync/async and settings | - |
Common Configuration Scenarios
Authentication
Recommended: Use the PAYI_API_KEY
environment variable. This avoids hardcoding credentials in your source code.
# Set environment variable (e.g., in your .env file or system environment)
export PAYI_API_KEY="your-api-key"
from payi import Payi
# Client automatically picks up the key from the environment
client = Payi()
Alternative: Pass the key directly during initialization (less secure, mainly for quick tests or specific scenarios where environment variables aren't feasible).
from payi import Payi
client = Payi(api_key="your-api-key") # Avoid this in production code
Custom Timeouts
Adjust network timeouts based on expected API response times or network conditions.
from payi import Payi, Timeout
client = Payi(
# Use the Timeout object for detailed control
timeout=Timeout(timeout=90.0, connect=10.0) # 90s request, 10s connect
)
Custom Retry Settings
Modify how the client handles temporary network issues or server errors (like 5xx status codes).
from payi import Payi
# Increase retries if operating in an environment with unreliable network connectivity
client = Payi(max_retries=5)
Custom Base URL
Point the client to a different Pay-i API endpoint. This is necessary for:
- Private Deployments: Connecting to your self-hosted or privately deployed Pay-i instance.
- Staging/Testing Environments: Using non-production Pay-i environments.
Recommended: Use the PAYI_BASE_URL
environment variable.
# Set environment variable for a private deployment
export PAYI_BASE_URL="https://payi.my-company.internal"
from payi import Payi
# Client automatically picks up the URL from the environment
client = Payi()
Alternative: Pass the URL directly during initialization.
from payi import Payi
# Example for a staging environment
client = Payi(base_url="https://api-staging.pay-i.com")
# Example for a private deployment
# client = Payi(base_url="https://payi.my-company.internal")
Default Headers
Send specific headers with every API request made by the client.
from payi import Payi
client = Payi(
default_headers={
"X-Internal-Service": "BillingProcessor",
"X-Request-Source": "BatchJob"
}
)
Usage Patterns
Synchronous Usage
When using the Payi
client, operations are performed synchronously:
from payi import Payi
client = Payi()
# Send telemetry data (synchronous)
response = client.ingest.units(
category="openai",
resource="chat",
units={"input": {"value": 10}, "output": {"value": 50}}
)
# Work with the response directly
request_id = response.xproxy_result.request_id
print(f"Ingested request: {request_id}")
This example shows a basic event submission. For a comprehensive guide on using ingest.units
for manual event submission, including all parameters and advanced scenarios, see the SDK Event Submission (Ingest API) documentation.
Asynchronous Usage
When using the AsyncPayi
client, operations are performed asynchronously:
import asyncio
from payi import AsyncPayi
async_client = AsyncPayi()
async def ingest_event():
# Send telemetry data (asynchronous)
response = await async_client.ingest.units(
category="openai",
resource="chat",
units={"input": {"value": 10}, "output": {"value": 50}}
)
# Work with the response
request_id = response.xproxy_result.request_id
print(f"Ingested request: {request_id}")
return response
# Run the async function
asyncio.run(ingest_event())
This example shows a basic asynchronous event submission. For a comprehensive guide on using ingest.units
for manual event submission, including all parameters and advanced scenarios, see the SDK Event Submission (Ingest API) documentation.
Pagination in List Methods
All resources in the Pay-i SDK provide a list()
method that returns collections of objects (e.g., client.limits.list()
, client.categories.list()
). The SDK handles pagination automatically, so you can write simple code that processes all items regardless of collection size:
# Simple iteration through all items (pagination handled automatically)
for limit in client.limits.list():
print(f"Limit: {limit.limit_name}")
Behind the scenes, the SDK makes multiple API calls as needed when you iterate through the results. This means your code can process large collections without manually handling pagination tokens or making multiple explicit API calls.
Pagination Parameters
While automatic pagination works for most use cases, all list()
methods support these optional pagination parameters:
client.resource_name.list(
cursor=None, # Token for fetching a specific page
limit=None, # Maximum items per page (default: 25, max: 100)
sort_ascending=None # Sort order (true for ascending, false for descending)
)
Note: These parameters are inherited from the SDK framework and are primarily for advanced use cases. Most users don't need to specify them. The Pay-i service defaults to returning 25 elements per page when no limit is specified.
Examples with Pagination Parameters
# Get the first 10 items
first_page = client.limits.list(limit=10)
# Get items in ascending order
ascending_items = client.limits.list(sort_ascending=True)
# Advanced: Manual pagination with cursor
first_page = client.limits.list(limit=20)
if first_page.has_more:
# Get the next page using the cursor from the first page
second_page = client.limits.list(cursor=first_page.next_cursor, limit=20)
For most applications, we recommend the simple approach of letting the SDK handle pagination automatically through iteration.
Raw and Streaming Responses
Raw Responses
To access the raw HTTP response:
# Synchronous
raw_response = client.with_raw_response.ingest.units(...)
# Access HTTP-level details
status_code = raw_response.status_code
headers = raw_response.headers
Streaming Responses
For efficient handling of large responses:
# Synchronous
streamed_response = client.with_streaming_response.ingest.units(...)
Client Customization
Create a modified client with updated settings:
# Create a new client with different options
new_client = client.with_options(
timeout=Timeout(timeout=10.0),
max_retries=3,
default_headers={"X-Custom-Header": "value"}
)
Integration with Instrumentation
The client classes integrate with the Pay-i instrumentation functionality:
from payi import Payi
from payi.lib.instrument import payi_instrument
# Create a custom client
client = Payi(timeout=Timeout(timeout=60.0))
# Pass to instrumentation system
payi_instrument(payi=client)
For more details on this integration, see the payi_instrument()
documentation.
Error Handling
The client provides standardized error handling:
from payi import Payi
from payi.errors import AuthenticationError, RateLimitError, BadRequestError
client = Payi()
try:
response = client.ingest.units(...)
except AuthenticationError:
print("Authentication failed - check your API key")
except RateLimitError:
print("Rate limit exceeded - slow down requests")
except BadRequestError as e:
print(f"Bad request: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
Best Practices
- Environment Variables: Store API keys in environment variables rather than hardcoding them
- Appropriate Timeouts: Configure timeouts based on your application's needs
- Error Handling: Implement proper error handling for API interactions
- Client Reuse: Create client instances once and reuse them throughout your application
- Async When Appropriate: Use
AsyncPayi
for asynchronous applications or concurrent operations
Updated about 7 hours ago