API Documentation
Base URL: https://api.snaprx.co
Overview
The SnapRx API is a RESTful JSON API built with FastAPI. All endpoints return JSON responses. Authentication uses JWT bearer tokens. Most public endpoints (search, prices, coupons, recalls) work without authentication.
Format
JSON (application/json)
Auth
Bearer Token (JWT)
Rate Limit
60 req/min global; per-route limits vary
Versioning
URL path (/v1/)
System
/health
Health check. Returns API version.
/health/ready
Readiness probe. Verifies database and Redis connectivity.
Authentication
Auth endpoints use the /auth prefix (no /v1). All authenticated endpoints require a Bearer token in the Authorization header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
/auth/register
Create a new user account. Password requires 8+ chars, uppercase, lowercase, and digit.
{
"email": "user@example.com",
"password": "SecurePass1",
"full_name": "Jane Doe",
"zip_code": "10001",
"timezone": "America/New_York"
}
{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"full_name": "Jane Doe",
"zip_code": "10001",
"timezone": "America/New_York",
"is_verified": false,
"created_at": "2026-03-05T12:00:00Z"
},
"access_token": "eyJhbGciOi...",
"refresh_token": "eyJhbGciOi...",
"token_type": "bearer"
}
/auth/login
Authenticate and receive access + refresh tokens. Rate limited: 10/min.
{
"access_token": "eyJhbGciOi...",
"refresh_token": "eyJhbGciOi...",
"token_type": "bearer",
"expires_in": 1800
}
/auth/refresh
Exchange a refresh token for a new access token.
/auth/oauth
Authenticate via Google or Apple OAuth. Provide provider ("google" or "apple") and provider_token.
/auth/logout
Revoke the current refresh token. Requires authentication.
/auth/forgot-password
Request a password reset email. Always returns 200 to prevent email enumeration.
/auth/me
Get the current authenticated user's profile. Requires authentication.
Drugs & Search
/v1/drugs/search?q={query}
Search for medications by name. Uses spell correction, pg_trgm fuzzy matching, and RxNorm API fallback. q must be at least 2 characters. No authentication required.
{
"query": "metformin",
"corrected_query": null,
"results": [
{
"id": "8939a932-4b0a-41c8-bd6e-...",
"name": "Metformin",
"generic_name": "metformin",
"brand_names": ["Glucophage"],
"manufacturer_type": "generic",
"drug_class": "Biguanide",
"form": "tablet",
"dosage": "500mg",
"rxcui": null
}
],
"total": 1
}
/v1/drugs/autocomplete?q={query}
Fast autocomplete suggestions for drug names. Returns up to 10 suggestions.
/v1/drugs/{drug_id}
Get detailed drug information including uses, side effects, warnings, contraindications, available dosages, and storage instructions. drug_id must be a UUID.
/v1/drugs/{drug_id}/label
Get the full FDA label information for a drug from openFDA.
Price Comparison
/v1/prices/compare?name={drug_name}&quantity={qty}
Compare pharmacy prices for a medication. Provide at least one of: drug_id (UUID), name (string), or ndc (string). Optional: quantity (default 30), location (ZIP code), include_mail_order, include_membership.
{
"drug": {
"id": "8939a932-...",
"name": "Metformin",
"generic_name": "metformin",
"dosage": "500mg",
"form": "tablet"
},
"quantity": 30,
"days_supply": 30,
"prices": [
{
"pharmacy": {
"id": "c5b90b53-...",
"slug": "cvs",
"name": "CVS Pharmacy",
"pharmacy_type": "RETAIL"
},
"price": "3.60",
"retail_price": "29.69",
"price_type": "coupon",
"savings_pct": 87.8
}
],
"lowest_price": "3.60",
"highest_price": "36.29",
"potential_savings": "32.69",
"total_pharmacies": 5
}
/v1/prices/best?name={drug_name}&quantity={qty}
Get just the single best price for a drug.
/v1/prices/pharmacies
List all pharmacy chains with pricing data. Supports pharmacy_type filter (RETAIL, MAIL_ORDER, ONLINE).
Coupons
/v1/coupons/search?drug_name={name}&quantity={qty}
Search for available coupons. Provide drug_name or drug_id. Optional: quantity (default 30), source (goodrx, singlecare, rxsaver).
{
"drug_name": "Metformin",
"drug_id": "8939a932-...",
"quantity": 30,
"coupons": [
{
"id": "b9939129-...",
"source": "goodrx",
"coupon_type": "discount_card",
"bin_number": "015995",
"pcn": "GDC",
"group_number": "GDC10406",
"member_id": "GOO00100406",
"price": "3.23",
"retail_price": "32.30",
"savings_pct": 90.0,
"pharmacy": { "name": "Costco Pharmacy" }
}
],
"lowest_price": "3.23",
"potential_savings": "29.07",
"total": 21
}
/v1/coupons/{coupon_id}
Get details for a specific coupon.
/v1/coupons/saved
Save a coupon to your wallet. Requires authentication.
Drug Interactions
/v1/interactions/check
Check drug-drug interactions for a list of medications. Rate limited: 20/min.
{
"drugs": ["warfarin", "aspirin"]
}
{
"medications_checked": ["warfarin", "aspirin"],
"total_interactions": 1,
"interactions": [
{
"drug_a": "Warfarin",
"drug_b": "Aspirin",
"severity": "major",
"description": "Increased bleeding risk. NSAIDs inhibit platelets.",
"clinical_effects": "May increase anticoagulant effect and hemorrhage risk.",
"management": "Avoid combination. Monitor INR if necessary.",
"source": "fda"
}
],
"critical_alerts": [...],
"severity_counts": { "major": 1, "moderate": 0, "minor": 0 },
"risk_level": "high"
}
/v1/interactions/quick?drug_a={name}&drug_b={name}
Quick check for interactions between two specific drugs.
Pharmacies
/v1/pharmacies/nearby?zip_code={zip}&radius_miles={mi}
Search for pharmacies near a location. Provide either zip_code or latitude/longitude. Optional: radius_miles (default 10, max 100), pharmacy_type (retail, mail_order, online, 24hr), limit (default 20).
/v1/pharmacies/chains
List all active pharmacy chains with location counts and website URLs.
/v1/pharmacies/{pharmacy_id}
Get detailed info for a specific pharmacy location.
FDA Recalls
/v1/recalls/?drug_name={name}
Search FDA enforcement recalls by drug name. Data sourced from openFDA in real-time. Optional: limit (default 10).
/v1/recalls/check/{drug_name}
Check if a specific drug has any active (Ongoing) FDA recalls. Returns has_active_recall boolean and list of active recalls.
Bottle Scanning
/v1/scan/bottle
Scan a prescription bottle label. Provide image_base64 (base64-encoded image) or raw_text (OCR text). Uses Google Cloud Vision with Tesseract fallback. Rate limited: 10/min.
{
"success": true,
"drug_name": "LISINOPRIL",
"dosage": "10 MG",
"form": "tablet",
"quantity": 30,
"directions": "Take 1 tablet by mouth once daily",
"ndc": "68180051401",
"matched_drug": {
"id": "7fdcbac4-...",
"name": "Lisinopril"
},
"confidence": 0.87,
"warnings_detected": []
}
/v1/scan/pill
Identify a pill by imprint, color, and shape. imprint is required. Optional: color, shape.
{
"success": true,
"matches": [
{
"drug_name": "Oxycodone/Acetaminophen",
"strength": "10/325 mg",
"manufacturer": "Mallinckrodt",
"imprint": "M523",
"color": "white",
"shape": "oval",
"ndc": "00406-0523",
"confidence": 0.70,
"image_url": "https://data.lhncbc.nlm.nih.gov/..."
}
]
}
/v1/scan/pill/suggest?q={imprint_query}
Autocomplete pill imprints. Returns suggestions matching the query with drug name, strength, color, shape, and manufacturer.
Medications Cabinet
/v1/medications
List all medications in the user's cabinet. Requires authentication.
/v1/medications
Add a medication to the user's cabinet with dosage schedule. Requires authentication.
Compliance & Legal
/v1/compliance/controlled-substance/{dea_schedule}
Get controlled substance restrictions for a DEA schedule (I through V). Public endpoint.
/v1/legal/documents
List the current version of every legal document. Public endpoint.
/v1/legal/documents/{type}
Get a specific legal document. Valid types: tos, privacy_policy, hipaa_notice, discount_card_terms, arbitration_agreement.
App & Waitlist
/v1/app/version-check
Check if the client app version requires an update. Fields: platform ("ios" or "android"), current_version (semver string).
/v1/waitlist
Join the waitlist. Provide email in the request body.
Error Responses
All errors follow a consistent envelope format:
{
"error": {
"type": "invalid_request_error",
"code": "validation_error",
"detail": "Human-readable error message",
"errors": [
{ "field": "body.email", "message": "Field required" }
]
}
}
| Status Code | Meaning |
|---|---|
| 400 | Bad Request — invalid input or missing required parameters |
| 401 | Unauthorized — missing or invalid token |
| 403 | Forbidden — insufficient permissions |
| 404 | Not Found — resource doesn't exist |
| 409 | Conflict — resource already exists |
| 422 | Validation Error — request body schema validation failed |
| 429 | Too Many Requests — rate limit exceeded (Retry-After header included) |
| 500 | Internal Server Error |
Rate Limiting
Rate limit headers are included in every response:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1711000000
| Scope | Limit |
|---|---|
| Global (all endpoints) | 60 req/min per IP |
| Auth: register | 5 req/min per IP |
| Auth: login | 10 req/min per IP |
| Auth: forgot-password | 3 req/min per IP |
| Interactions: check | 20 req/min per IP |
| Scan: bottle, pill | 10 req/min per IP |