Official Python SDK for the Vairified Partner API
Project description
Vairified Python SDK
Official Python SDK for the Vairified Partner API
Player ratings, search, and match submission
Python SDK for integrating with the Vairified player rating platform. Async-first, object-oriented design for easy integration.
Installation
pip install vairified
Or with UV:
uv add vairified
Quick Start
import asyncio
from vairified import Vairified
async def main():
async with Vairified(api_key="vair_pk_xxx") as client:
# Get a member - automatically subscribes to their rating updates
member = await client.get_member("clerk_user_123")
print(f"{member.name}: {member.rating}")
print(f"Verified: {member.is_vairified}")
print(f"Best rating: {member.rating_splits.best}")
asyncio.run(main())
Features
Search for Players
async with Vairified(api_key="vair_pk_xxx") as client:
# Search with filters
results = await client.search(
city="Austin",
state="TX",
rating_min=3.5,
rating_max=4.5,
vairified_only=True,
limit=20,
)
# Iterate over results
for player in results:
print(f"{player.name}: {player.rating}")
# Pagination
print(f"Page {results.page} of {results.pages}")
if results.has_more:
next_page = await results.next_page()
Find a Player by Name
async with Vairified(api_key="vair_pk_xxx") as client:
player = await client.find_player("John Smith")
if player:
print(f"Found: {player.name} ({player.rating})")
Submit Match Results
from datetime import datetime
from vairified import Vairified, Match
async with Vairified(api_key="vair_pk_xxx") as client:
# Doubles match: 11-9, 11-7
match = Match(
event="Weekly League",
bracket="4.0 Doubles",
date=datetime.now(),
team1=("player1_id", "player2_id"),
team2=("player3_id", "player4_id"),
scores=[(11, 9), (11, 7)],
)
result = await client.submit_match(match)
if result:
print(f"Submitted {result.num_games} games")
# Singles match
singles = Match(
event="Club Singles",
bracket="Open Singles",
date=datetime.now(),
team1=("player1_id",),
team2=("player2_id",),
scores=[(11, 8), (9, 11), (11, 6)],
)
await client.submit_match(singles)
Get Rating Updates
async with Vairified(api_key="vair_pk_xxx") as client:
# First, look up members to subscribe to their updates
await client.get_member("user_1")
await client.get_member("user_2")
# Later, check for rating changes
updates = await client.get_rating_updates()
for update in updates:
direction = "improved" if update.improved else "dropped"
print(f"{update.member_id} {direction}: {update.previous_rating:.2f} -> {update.new_rating:.2f}")
# Get the full member profile
member = await update.get_member()
OAuth Connect Flow
Connect players to your application using OAuth to access their profile and rating data.
import secrets
from vairified import Vairified, OAuthError
async with Vairified(api_key="vair_pk_xxx") as client:
# Step 1: Start authorization
state = secrets.token_urlsafe(32) # CSRF protection
auth = await client.start_oauth(
redirect_uri="https://myapp.com/oauth/callback",
scopes=["profile:read", "rating:read", "match:submit"],
state=state,
)
# Redirect user to auth.authorization_url
print(f"Redirect to: {auth.authorization_url}")
# Step 2: Handle callback (in your /oauth/callback route)
async with Vairified(api_key="vair_pk_xxx") as client:
# Exchange code for tokens
tokens = await client.exchange_token(
code=request.query_params["code"],
redirect_uri="https://myapp.com/oauth/callback",
)
# Store tokens securely
player_id = tokens.player_id
access_token = tokens.access_token
refresh_token = tokens.refresh_token
# Now you can access the player's data
member = await client.get_member(player_id)
print(f"Connected: {member.name} ({member.rating})")
# Step 3: Refresh expired tokens
async with Vairified(api_key="vair_pk_xxx") as client:
try:
new_tokens = await client.refresh_access_token(stored_refresh_token)
# Update stored tokens
except OAuthError as e:
if e.error_code == "invalid_grant":
# Token revoked, user needs to re-authorize
pass
Available OAuth Scopes
| Scope | Description |
|---|---|
profile:read |
Name, location, verification status |
profile:email |
Email address |
rating:read |
Current rating and rating splits |
rating:history |
Complete rating history |
match:submit |
Submit matches on behalf of user |
webhook:subscribe |
Rating change notifications |
Revoke Connection
async with Vairified(api_key="vair_pk_xxx") as client:
await client.revoke_connection("vair_mem_xxx")
Models
Player
player.id # UUID or member ID
player.member_id # Legacy member ID
player.name # "John Smith"
player.first_name # "John"
player.last_name # "Smith"
player.rating # 4.25
player.is_vairified # True/False
player.rating_splits # RatingSplits object
player.city # "Austin"
player.state # "TX"
player.verified_rating # Best verified rating
Member (extends Player)
member.email # Email address
await member.refresh() # Refresh data from API
RatingSplits
Access ratings by category:
splits = member.rating_splits
splits.open # Open division rating
splits.gender # Same-gender doubles rating
splits.mixed # Mixed doubles rating
splits.recreational # Recreational rating
splits.singles # Singles rating
splits.best # Best available rating
splits.get("50_and_up") # Age bracket rating
Match
match = Match(
event="Weekly League",
bracket="4.0 Doubles",
date=datetime.now(),
team1=("id1", "id2"), # Player IDs for team 1
team2=("id3", "id4"), # Player IDs for team 2
scores=[(11, 9), (11, 7)], # Game scores
location="Austin Club", # Optional
match_type="SIDEOUT", # Default: "SIDEOUT"
source="PARTNER", # Default: "PARTNER"
)
match.format # "DOUBLES" or "SINGLES"
match.winner # 1 or 2 (0 if tie)
match.score_summary # "11-9, 11-7"
match.identifier # Auto-generated unique ID
MatchResult
result = await client.submit_matches([match1, match2])
result.success # True/False
result.num_matches # Number processed
result.num_games # Games recorded
result.dry_run # True if validation only
result.message # Human-readable message
result.errors # List of errors
bool(result) # True if successful
SearchResults
results.players # List of Player objects
results.total # Total matching players
results.page # Current page
results.pages # Total pages
results.has_more # More pages available
await results.next_page() # Get next page
bool(results) # True if has players
Configuration
from vairified import Vairified
# Basic usage
client = Vairified(api_key="vair_pk_xxx")
# Use staging for development/testing
client = Vairified(api_key="vair_pk_xxx", env="staging")
# Custom configuration
client = Vairified(
api_key="vair_pk_xxx",
timeout=30.0,
)
Environment Variables
export VAIRIFIED_API_KEY="vair_pk_xxx"
# API key read from environment
async with Vairified() as client:
...
Dry-Run Mode (Dev Keys)
If your API key has the dry-run scope, match submissions are validated but not persisted. This is useful for testing integrations without affecting production data.
# With a dry-run API key
async with Vairified(api_key="vair_pk_dev_xxx") as client:
result = await client.submit_matches([match1, match2])
if result.dry_run:
print(f"Validation passed: {result.num_games} games would be created")
print(result.message)
Request a dry-run API key from your Vairified partner contact for integration testing.
Error Handling
from vairified import (
Vairified,
VairifiedError,
RateLimitError,
AuthenticationError,
NotFoundError,
OAuthError,
)
async with Vairified(api_key="vair_pk_xxx") as client:
try:
member = await client.get_member("user_123")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after} seconds")
except AuthenticationError:
print("Invalid API key")
except NotFoundError:
print("Member not found")
except OAuthError as e:
print(f"OAuth error: {e.message} (code: {e.error_code})")
except VairifiedError as e:
print(f"API error: {e.message} (status: {e.status_code})")
Development
git clone https://github.com/Vairified/vairified.py.git
cd vairified.py
uv sync --all-extras
uv run pytest
License
MIT License - see LICENSE for details.
Project details
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 vairified-0.1.0.tar.gz.
File metadata
- Download URL: vairified-0.1.0.tar.gz
- Upload date:
- Size: 65.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
551bf436882684799b8b61d16a568ecbc5835c62050af20aa8479501464d95d3
|
|
| MD5 |
6202a7c61ce04e7ff71d6ed406b2f8f2
|
|
| BLAKE2b-256 |
63cb9a9deb7151479bc58395f3d2d8aa6726c9e972c69851068d2d077483cd81
|
Provenance
The following attestation bundles were made for vairified-0.1.0.tar.gz:
Publisher:
release.yml on Vairified/vairified.py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vairified-0.1.0.tar.gz -
Subject digest:
551bf436882684799b8b61d16a568ecbc5835c62050af20aa8479501464d95d3 - Sigstore transparency entry: 868316753
- Sigstore integration time:
-
Permalink:
Vairified/vairified.py@de69b9b2eb9ac58ebdd7d68739ac939f40c81ba8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Vairified
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@de69b9b2eb9ac58ebdd7d68739ac939f40c81ba8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file vairified-0.1.0-py3-none-any.whl.
File metadata
- Download URL: vairified-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.0 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 |
5f7f7b125ef011ae06d0b195f4e2aa3a327637c1d8b95be2ec9dec3c10a12b7a
|
|
| MD5 |
76f98cece7f103e8132cbd87f27f8843
|
|
| BLAKE2b-256 |
a395fa935a15c912eaca5c5bf51e96fe29c1025662201ff7f49d59ff82c78197
|
Provenance
The following attestation bundles were made for vairified-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Vairified/vairified.py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vairified-0.1.0-py3-none-any.whl -
Subject digest:
5f7f7b125ef011ae06d0b195f4e2aa3a327637c1d8b95be2ec9dec3c10a12b7a - Sigstore transparency entry: 868316756
- Sigstore integration time:
-
Permalink:
Vairified/vairified.py@de69b9b2eb9ac58ebdd7d68739ac939f40c81ba8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Vairified
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@de69b9b2eb9ac58ebdd7d68739ac939f40c81ba8 -
Trigger Event:
push
-
Statement type: