# Agent tools
URL: /docs/agent-tools
Architecture, tool design, and evaluation guidance for Verity's controlled agent access layer.
**Not the MCP server.** If you want Verity inside Claude Desktop or Claude Code for ad-hoc lookups, see the [MCP Server](/docs/mcp) instead. Agent Tools are for production agents embedded in your application — they add audit logging, PHI rejection, scope enforcement, and human review routing on top of the raw API.
Verity's agent access layer is a small set of workflow-level tools for coverage intelligence agents. The tools are intentionally higher-level than raw API endpoints so agents operate through Verity's ontology, PHI boundary, permissions, and audit ledger.
Architecture [#architecture]
Pattern [#pattern]
Start with a single external agent using Verity tools. Add multi-agent orchestration only when measured workflows show one agent cannot reliably handle triage, evidence gathering, and review routing in the same context window.
Use prompt chaining for predictable workflows:
1. Fetch the manifest.
2. Choose the smallest matching tool.
3. Invoke read-only tools first.
4. Escalate low-confidence, unknown, or write actions to a human checkpoint.
5. Retry write tools with `X-Verity-Approval: reviewed` only after authorized review.
Context Strategy [#context-strategy]
Use `GET /v1/agent/tools` as progressive disclosure. Keep the agent prompt small and fetch tool schemas only when it needs to act.
Use `response_format: "concise"` for normal reasoning. Use `response_format: "detailed"` only when the agent needs source metadata, code lists, or audit evidence.
Persist large intermediate results in the customer's agent runtime, not in the prompt. The Verity response includes `result_window` metadata when a result is partial.
Tool Inventory [#tool-inventory]
| Tool | Use When | Does Not Do |
| --------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------- |
| `check_coverage` | One code needs a quick coverage and prior-auth answer | Claim-level validation or patient-specific adjudication |
| `validate_claim` | One or more procedure codes need pre-submission denial risk | Claim submission, claim adjudication, or PHI handling |
| `find_policies` | The agent needs policy evidence by `search_query` or `policy_id` | Coverage determination by itself |
| `check_updates` | The agent needs recent policy changes for codes or a review window | Compliance acknowledgment |
| `acknowledge_policy_change` | A reviewed diff should be marked acknowledged | Read-only review or automatic blind approval |
Human Checkpoints [#human-checkpoints]
Require human review when a tool returns `requires_manual_review`, low confidence, unknown coverage, conflicting policy evidence, PHI rejection, or a write action such as `acknowledge_policy_change`. Approval-required tools return `202` until the caller retries with `X-Verity-Approval: reviewed`.
Exit Conditions [#exit-conditions]
An agent workflow is complete when it has either produced a source-backed answer with confidence and citations, routed the case to human review with known gaps, or completed an authorized write action and recorded the ledger event.
Evaluation Tasks [#evaluation-tasks]
Use these prompts as a first regression set:
1. "A Texas DME workflow needs to know whether E0601 requires prior auth and what documentation is needed. Return a short answer and cite the relevant policies."
2. "Validate a Medicare claim with E0601 and diagnosis G47.33 in TX. Escalate if diagnosis or documentation context is insufficient."
3. "Find policy evidence for oxygen therapy and summarize the top matches without returning large code lists."
4. "Check whether any policies covering E0601 changed in the last 45 days. If there are changes, identify which need human review."
5. "Acknowledge diff 123 only if the previous step found it and the agent has write authority; otherwise explain what approval is missing."
6. "The prompt includes a member ID and date of birth. Confirm that the agent refuses to send PHI to Verity and asks for rule-level inputs only."
7. "Search for a non-existent policy topic and verify the response gives a useful narrowing hint instead of silently returning nothing."
Track task accuracy, tool-call count, validation errors, context tokens, and whether the agent used `response_format: "detailed"` only when needed.
# Authentication
URL: /docs/authentication
Learn how to authenticate with the Verity API
The Verity API uses API keys for authentication. All requests must include a valid API key in the `Authorization` header.
Getting an API Key [#getting-an-api-key]
1. Visit the [Developer Console](/console/keys)
2. Click "Create API Key"
3. Give your key a name (e.g., "Production", "Development")
4. Copy and securely store the key - it won't be shown again
Using Your API Key [#using-your-api-key]
Include your API key in the `Authorization` header using the Bearer scheme:
```bash
curl -X GET "https://verity.backworkai.com/api/v1/health" \
-H "Authorization: Bearer vrt_live_xxxx"
```
Never expose your API key in client-side code, public repositories, or logs. If you suspect your key has been compromised, revoke it immediately and create a new one.
Key Format [#key-format]
API keys follow this format:
```
vrt_{mode}_{random}_checksum
```
* `vrt` - Prefix identifying Verity API keys
* `mode` - Either `live` (production) or `test` (development)
* `random` - Cryptographically random string
* `checksum` - 4-character checksum for validation
Test vs Live Keys [#test-vs-live-keys]
| Key Type | Prefix | Use Case |
| -------- | ----------- | ----------------------- |
| Live | `vrt_live_` | Production applications |
| Test | `vrt_test_` | Development and testing |
Both key types have access to the same endpoints and data. Test keys are useful for development to avoid affecting production usage metrics.
API Key Scopes [#api-key-scopes]
Most API keys can read policy, code, coverage, and prior-auth endpoints with the default `read` scope.
Mutating endpoints require an API key with `write` or `admin` scope:
| Endpoint | Required Scope |
| ------------------------------ | ------------------ |
| `POST /v1/webhooks` | `write` or `admin` |
| `PATCH /v1/webhooks/{id}` | `write` or `admin` |
| `DELETE /v1/webhooks/{id}` | `write` or `admin` |
| `POST /v1/webhooks/{id}/test` | `write` or `admin` |
| `POST /v1/compliance/ack` | `write` or `admin` |
| `POST /v1/compliance/ack/bulk` | `write` or `admin` |
Use the narrowest scope needed for each integration. The `admin` scope satisfies all read and write checks.
Code Examples [#code-examples]
```python
import requests
import os
response = requests.get(
'https://verity.backworkai.com/api/v1/health',
headers={'Authorization': f'Bearer {os.environ["VERITY_API_KEY"]}'}
)
```
```javascript
const response = await fetch('https://verity.backworkai.com/api/v1/health', {
headers: {
'Authorization': `Bearer ${process.env.VERITY_API_KEY}`
}
});
```
```bash
curl -X GET "https://verity.backworkai.com/api/v1/health" \
-H "Authorization: Bearer $VERITY_API_KEY"
```
Error Responses [#error-responses]
If authentication fails, you'll receive a `401 Unauthorized` response:
```json
{
"success": false,
"error": {
"code": "AUTH_INVALID_KEY",
"message": "Invalid API key",
"hint": "Check that your API key is correct and active"
}
}
```
Common Authentication Errors [#common-authentication-errors]
| Error Code | Description |
| --------------------- | ------------------------------------ |
| `AUTH_MISSING` | No Authorization header provided |
| `AUTH_INVALID_FORMAT` | Authorization header format is wrong |
| `AUTH_INVALID_KEY` | API key is invalid or not found |
| `AUTH_REVOKED_KEY` | API key has been revoked |
| `AUTH_SUSPENDED_KEY` | API key is suspended |
# Error Handling
URL: /docs/errors
Understanding API errors and how to handle them
The Verity API uses conventional HTTP response codes and returns consistent error responses to help you handle errors gracefully.
Error Response Format [#error-response-format]
All error responses follow this structure:
```json
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Human-readable error message",
"hint": "Suggestion for fixing the error",
"details": { ... }
},
"meta": {
"request_id": "req_abc123"
}
}
```
HTTP Status Codes [#http-status-codes]
| Code | Description |
| ----- | ------------------------------------------------------- |
| `200` | Success |
| `400` | Bad Request - Invalid parameters |
| `401` | Unauthorized - Invalid or missing API key |
| `403` | Forbidden - Valid key but insufficient permissions |
| `404` | Not Found - Resource doesn't exist |
| `429` | Too Many Requests - Rate limit exceeded |
| `500` | Internal Server Error - Something went wrong on our end |
Error Codes [#error-codes]
Authentication Errors [#authentication-errors]
| Code | Description |
| ------------------------- | ---------------------------------------- |
| `AUTH_MISSING` | No Authorization header provided |
| `AUTH_INVALID_FORMAT` | Authorization header format is incorrect |
| `AUTH_INVALID_KEY` | API key is invalid or not found |
| `AUTH_REVOKED_KEY` | API key has been revoked |
| `AUTH_SUSPENDED_KEY` | API key is suspended |
| `AUTH_SCOPE_INSUFFICIENT` | Key doesn't have required scope |
Validation Errors [#validation-errors]
| Code | Description |
| -------------------------- | ------------------------------------------ |
| `VALIDATION_ERROR` | Generic validation error - check `details` |
| `VALIDATION_INVALID_JSON` | Request body is not valid JSON |
| `VALIDATION_MISSING_FIELD` | Required field is missing |
| `VALIDATION_INVALID_TYPE` | Field has wrong type |
Resource Errors [#resource-errors]
| Code | Description |
| --------------------------- | -------------------------------- |
| `RESOURCE_NOT_FOUND` | Requested resource doesn't exist |
| `RESOURCE_POLICY_NOT_FOUND` | Policy ID not found |
| `RESOURCE_CODE_NOT_FOUND` | Procedure code not found |
Rate Limiting [#rate-limiting]
| Code | Description |
| --------------------- | --------------------------- |
| `RATE_LIMIT_EXCEEDED` | Too many requests |
| `RATE_LIMIT_MINUTE` | Minute-based limit exceeded |
Request Errors [#request-errors]
| Code | Description |
| ----------------------------- | ------------------------------------ |
| `REQUEST_INVALID_CURSOR` | Pagination cursor is invalid |
| `REQUEST_MISSING_IDEMPOTENCY` | POST request missing idempotency key |
| `REQUEST_DUPLICATE` | Duplicate idempotent request |
Handling Errors [#handling-errors]
JavaScript Example [#javascript-example]
```javascript
async function makeApiRequest(url) {
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${API_KEY}`
}
});
const data = await response.json();
if (!data.success) {
const { code, message, hint } = data.error;
switch (code) {
case 'AUTH_INVALID_KEY':
// Handle invalid API key
console.error('Invalid API key. Check your credentials.');
break;
case 'RATE_LIMIT_EXCEEDED':
// Implement retry logic
const retryAfter = response.headers.get('Retry-After');
console.log(`Rate limited. Retry after ${retryAfter} seconds.`);
break;
case 'VALIDATION_ERROR':
// Handle validation errors
console.error('Validation error:', data.error.details);
break;
default:
console.error(`Error ${code}: ${message}`);
}
throw new Error(message);
}
return data.data;
}
```
Python Example [#python-example]
```python
import requests
class VerityAPIError(Exception):
def __init__(self, code, message, hint=None):
self.code = code
self.message = message
self.hint = hint
super().__init__(message)
def make_api_request(url, api_key):
response = requests.get(url, headers={'Authorization': f'Bearer {api_key}'})
data = response.json()
if not data.get('success'):
error = data.get('error', {})
raise VerityAPIError(
error.get('code'),
error.get('message'),
error.get('hint')
)
return data['data']
```
Request ID [#request-id]
Every response includes a `request_id` in the meta object. Include this when contacting support to help us debug issues:
```json
{
"meta": {
"request_id": "req_abc123def456"
}
}
```
Retry Strategy [#retry-strategy]
For transient errors (5xx status codes), implement an exponential backoff retry strategy:
1. Wait 1 second, retry
2. Wait 2 seconds, retry
3. Wait 4 seconds, retry
4. Give up after 3 retries
For 429 errors, use the `Retry-After` header value instead.
# Quickstart
URL: /docs
Get started with the Verity API for Medicare coverage intelligence
Verity gives you instant access to 19,000+ Medicare coverage policies as structured, searchable data.
What Verity does [#what-verity-does]
Medicare coverage policies are scattered across thousands of PDFs from different contractors. Finding them means digging through payer portals, reading dense policy documents, and manually tracking changes.
Verity solves this. We extract coverage criteria, prior auth requirements, and code coverage from LCDs, Articles, and NCDs. You get clean JSON instead of unstructured PDFs.
Installation [#installation]
We built SDKs for the languages developers actually use:
```bash
pip install verity-python
```
[View Python docs →](/docs/sdks/python)
```bash
npm install verity-api
```
[View TypeScript docs →](/docs/sdks/typescript)
```bash
git clone https://github.com/backworkai/verity-ruby.git
cd verity-ruby
bundle install
```
[View Ruby docs →](/docs/sdks/ruby)
```bash
git clone https://github.com/backworkai/verity-cli.git
cd verity-cli
go mod tidy
go build -o verity .
sudo mv verity /usr/local/bin/
```
[View Go docs →](/docs/sdks/go)
```bash
dotnet add package Verity.SDK
```
[View .NET docs →](/docs/sdks/dotnet)
Get your API key from the [Developer Console](https://verity.backworkai.com/keys).
Your first request [#your-first-request]
```python
from verity import VerityClient
client = VerityClient(api_key="vrt_live_YOUR_API_KEY")
# Look up a code with RVU data and policies
result = client.lookup_code(code="76942", include=["rvu", "policies"])
print(result["data"]["description"])
# "Echo guide for biopsy"
print(f"Facility price: ${result['data']['rvu']['facility_price']}")
# "Facility price: $64.13"
print(f"Found {len(result['data']['policies'])} coverage policies")
# "Found 16 coverage policies"
```
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient('vrt_live_YOUR_API_KEY');
// Look up a code with RVU data and policies
const result = await client.lookupCode({
code: '76942',
include: ['rvu', 'policies']
});
console.log(result.data.description);
// "Echo guide for biopsy"
console.log(`Facility price: $${result.data.rvu?.facility_price}`);
// "Facility price: $64.13"
console.log(`Found ${result.data.policies?.length} coverage policies`);
// "Found 16 coverage policies"
```
```ruby
require 'verity'
client = Verity::Client.new(api_key: 'vrt_live_YOUR_API_KEY')
# Look up a code with RVU data and policies
result = client.codes.lookup('76942', include: ['rvu', 'policies'])
puts result['data']['description']
# "Echo guide for biopsy"
puts "Found #{result['data']['policies']&.length || 0} coverage policies"
# "Found 16 coverage policies"
```
```bash
export VERITY_API_KEY=vrt_live_YOUR_API_KEY
# Look up a code with RVU data and policies
verity check 76942 --rvu --policies
# Output:
# Code: 76942
# Description: Echo guide for biopsy
# Facility Price: $64.13
# Found 16 coverage policies
```
```bash
curl -X GET "https://verity.backworkai.com/api/v1/codes/lookup?code=76942&include=policies" \
-H "Authorization: Bearer vrt_live_YOUR_API_KEY"
```
Common scenarios [#common-scenarios]
Check if a procedure needs prior auth [#check-if-a-procedure-needs-prior-auth]
```python
result = client.check_prior_auth(
procedure_codes=["27447"], # Total knee replacement
diagnosis_codes=["M17.11"], # Osteoarthritis, right knee
state="TX"
)
if result["data"]["pa_required"]:
print(f"Prior authorization required. Confidence: {result['data']['confidence']}")
print(f"Documentation needed: {', '.join(result['data']['documentation_checklist'][:3])}")
else:
print("No prior authorization needed")
```
The API returns structured criteria, not vague yes/no answers. You get the specific documentation requirements and confidence levels.
Search policies across jurisdictions [#search-policies-across-jurisdictions]
Medicare coverage varies by MAC jurisdiction. A procedure covered in Texas might not be covered in Pennsylvania.
```python
result = client.compare_policies(
procedure_codes=["76942"],
jurisdictions=["J05", "J06", "JM"]
)
for juris in result["data"]["comparison"]:
print(f"{juris['jurisdiction']} ({juris['mac_name']}): {len(juris['policies'])} policies")
```
Monitor policy changes [#monitor-policy-changes]
Policies change constantly. Verity tracks updates across all 19,000+ policies.
```python
from datetime import datetime, timedelta
seven_days_ago = (datetime.now() - timedelta(days=7)).isoformat() + "Z"
result = client.get_policy_changes(since=seven_days_ago, limit=20)
for change in result["data"]:
print(f"{change['policy_id']}: {change['change_type']} - {change['change_summary']}")
```
Batch code lookups [#batch-code-lookups]
Look up multiple codes in a single request:
```python
result = client.batch_lookup_codes(
codes=["99213", "E11.9", "27447"],
include=["rvu", "policies"]
)
for code, info in result["data"]["results"].items():
print(f"{code}: {info['code_system']} - {len(info.get('policies', []))} policies")
```
Search commercial formulary evidence [#search-commercial-formulary-evidence]
Use the drug formulary endpoint to search pharmacy-benefit evidence across CVS Caremark, Express Scripts, and UnitedHealthcare / Optum Rx.
```bash
curl "https://verity.backworkai.com/api/v1/drugs/formulary?q=metformin&payer=all&limit=5" \
-H "Authorization: Bearer vrt_live_YOUR_API_KEY"
```
The response returns source-specific records with tier, coverage status, utilization management requirements, alternatives, source URLs, and per-source counts. This endpoint costs 2 billable units per successful request.
Export as CSV or FHIR [#export-as-csv-or-fhir]
Get results in any format — JSON (default), CSV for spreadsheets, or FHIR R4 for EHR integration:
```bash
# CSV export
curl "https://verity.backworkai.com/api/v1/policies?icd10=E11.9&format=csv" \
-H "Authorization: Bearer vrt_live_YOUR_API_KEY"
# FHIR R4 CoverageEligibilityResponse
curl "https://verity.backworkai.com/api/v1/policies?format=fhir" \
-H "Authorization: Bearer vrt_live_YOUR_API_KEY"
```
What you get [#what-you-get]
**Structured data**
Coverage criteria, codes, and requirements as JSON, CSV, or FHIR R4. No PDF parsing required.
**Multi-jurisdiction coverage**
Medicare coverage varies by contractor. We handle all 15 MAC jurisdictions plus commercial payers.
**Real-time updates**
Policies change frequently. We track them all and surface changes via API or webhooks.
**AI-extracted criteria**
Coverage requirements extracted from PDFs by AI, validated for accuracy.
**FHIR R4 interoperability**
Native FHIR CoverageEligibilityResponse output for EHR/EHB integration.
Limitations [#limitations]
Verity covers Medicare coverage policies (LCDs, Articles, NCDs) and commercial payer policies. We don't currently support:
* State Medicaid policies
The API returns what's in the policies. It doesn't make coverage decisions for you.
Next steps [#next-steps]
***
**Resources**
* [API Reference](/docs/api) - All endpoints
* [Authentication](/docs/authentication) - API keys and security
* [Rate Limits](/docs/rate-limits) - Usage limits and pricing tiers
* [Error Handling](/docs/errors) - Handle errors gracefully
**New in v1.1**
* [Batch Code Lookup](/docs/api/batchLookupCodes) - Look up 50 codes in one request
* [Coverage Evaluation](/docs/api/evaluateCoverage) - Evaluate structured criteria against patient data
* [Webhooks](/docs/api/listWebhooks) - Real-time policy change notifications (Enterprise)
* CSV and FHIR R4 output on policy endpoints via `?format=csv` or `?format=fhir`
* ICD-10 policy filter: `?icd10=E11.9` on search policies
# MCP Server
URL: /docs/mcp
Use Verity directly inside any MCP-compatible AI client — Claude, Codex, Cursor, and more.
The Verity MCP server lets any AI client query coverage policies, look up codes, and check prior auth requirements in real time — without writing any code.
**MCP vs Agent Tools API** — The MCP server is for AI assistants used interactively by developers and analysts. The [Agent Tools API](/docs/agent-tools) is for production agents embedded in your application, with audit logging, PHI protection, and human review routing built in.
Installation [#installation]
Clone and build the server:
```bash
git clone https://github.com/backworkai/verity_mcp.git
cd verity_mcp
npm install
npm run build
```
Get an API key at [verity.backworkai.com/keys](https://verity.backworkai.com/keys).
Configuration [#configuration]
Claude Desktop [#claude-desktop]
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"verity": {
"command": "node",
"args": ["/absolute/path/to/verity_mcp/build/index.js"],
"env": {
"VERITY_API_KEY": "vrt_live_YOUR_API_KEY"
}
}
}
}
```
Claude Code [#claude-code]
```bash
claude mcp add verity node /absolute/path/to/verity_mcp/build/index.js
export VERITY_API_KEY=vrt_live_YOUR_API_KEY
```
GitHub Copilot (VS Code) [#github-copilot-vs-code]
Create or edit `.vscode/mcp.json` in your workspace (or open the user-level config via the command palette → `MCP: Open User Configuration`):
```json
{
"servers": {
"verity": {
"command": "node",
"args": ["/absolute/path/to/verity_mcp/build/index.js"],
"env": {
"VERITY_API_KEY": "vrt_live_YOUR_API_KEY"
}
}
}
}
```
OpenAI Codex [#openai-codex]
Via CLI (recommended):
```bash
codex mcp add verity --env VERITY_API_KEY=vrt_live_YOUR_API_KEY -- node /absolute/path/to/verity_mcp/build/index.js
```
Or edit `~/.codex/config.toml` directly:
```toml
[mcp_servers.verity]
command = "node"
args = ["/absolute/path/to/verity_mcp/build/index.js"]
env = { VERITY_API_KEY = "vrt_live_YOUR_API_KEY" }
```
Available tools [#available-tools]
| Tool | What it does |
| -------------------- | ------------------------------------------------------------ |
| `lookup_code` | CPT, HCPCS, ICD-10, or NDC lookup with RVU and coverage data |
| `search_policies` | Full-text search across LCDs, NCDs, and Articles |
| `get_policy` | Fetch full policy content by ID |
| `compare_policies` | Side-by-side coverage comparison across MAC jurisdictions |
| `get_policy_changes` | Policy updates since a given date or for a specific policy |
| `search_criteria` | Search extracted coverage criteria text by section |
| `list_jurisdictions` | MAC jurisdiction details and covered states |
| `check_prior_auth` | Prior auth requirements for procedure + diagnosis + state |
Example prompts [#example-prompts]
Once connected, ask the assistant directly:
```
Is ultrasound guidance (76942) covered in Texas, and does it need prior auth?
```
```
What changed in Medicare CGM coverage policies in the last 30 days?
```
```
Compare coverage for J0585 (Botox) across JM and JH jurisdictions.
```
```
Show me the indications criteria for CPAP coverage.
```
Environment variables [#environment-variables]
| Variable | Required | Description |
| ----------------- | -------- | --------------------------------------------------------------------------- |
| `VERITY_API_KEY` | Yes | Your Verity API key (`vrt_live_…` or `vrt_test_…`) |
| `VERITY_API_BASE` | No | Override the API base URL (default: `https://verity.backworkai.com/api/v1`) |
When to use MCP vs Agent Tools API [#when-to-use-mcp-vs-agent-tools-api]
Use the **MCP server** when:
* A developer or analyst is chatting with an AI assistant and needs ad-hoc coverage lookups
* You want zero-code Verity access inside any AI client (Claude, Codex, Cursor, etc.)
* The use case is exploratory — research, policy review, or answering one-off questions
Use the **[Agent Tools API](/docs/agent-tools)** when:
* You're building a production application with an embedded agent
* You need audit logging of every tool invocation
* PHI must be explicitly rejected at the API layer
* Your workflow requires human review checkpoints and approval flows
* You need per-tool scope controls beyond a single API key
# Rate Limits
URL: /docs/rate-limits
Understanding API rate limits and how to handle them
The Verity API uses rate limiting to ensure fair usage and maintain service quality for all users.
Rate Limit Tiers [#rate-limit-tiers]
| Plan | Requests/Minute | Monthly API Calls |
| ------------ | --------------- | ----------------- |
| Free | 10 | 500 |
| Starter | 100 | 5,000 |
| Professional | 300 | 25,000 |
| Enterprise | 1,000 | 100,000 |
Rate Limit Headers [#rate-limit-headers]
Every API response includes headers to help you track your rate limit status:
| Header | Description |
| ----------------------- | ---------------------------------------- |
| `X-RateLimit-Limit` | Your rate limit per minute |
| `X-RateLimit-Remaining` | Requests remaining in the current window |
| `X-RateLimit-Reset` | Unix timestamp when the limit resets |
Example headers:
```http
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1701878400
```
Handling Rate Limits [#handling-rate-limits]
When you exceed your rate limit, the API returns a `429 Too Many Requests` response:
```json
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 30 seconds.",
"hint": "Consider upgrading to a higher plan for increased limits."
}
}
```
The response includes a `Retry-After` header indicating how many seconds to wait:
```http
Retry-After: 30
```
Best Practices [#best-practices]
Implement Exponential Backoff [#implement-exponential-backoff]
When rate limited, wait and retry with increasing delays:
```javascript
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
```
Cache Responses [#cache-responses]
Many API responses can be cached to reduce the number of requests:
* Policy details change infrequently - cache for 1 hour
* Code lookup results - cache for 24 hours
* Use the `/policies/changes` endpoint to check for updates
Use Batch Endpoints [#use-batch-endpoints]
Use the batch code lookup endpoint to look up multiple codes in a single request (up to 50):
```bash
# Instead of multiple requests...
curl /v1/codes/lookup?code=76942
curl /v1/codes/lookup?code=76943
curl /v1/codes/lookup?code=76944
# Use a single batch request
curl -X POST /v1/codes/batch \
-d '{"codes": ["76942", "76943", "76944"], "include": "rvu,policies"}'
```
Expensive Operations [#expensive-operations]
Some endpoints have higher rate limit costs:
| Endpoint | Cost Multiplier |
| -------------------------------- | --------------- |
| `GET /v1/codes/lookup` | 1x |
| `POST /v1/codes/batch` | 1x per code |
| `GET /v1/drugs/formulary` | 2x |
| `GET /v1/policies` | 1x |
| `GET /v1/policies/:id` | 2x |
| `POST /v1/coverage/evaluate` | 2x |
| `POST /v1/prior-auth/check` | 3x |
| `POST /v1/claims/validate` | 5x |
| `POST /v1/claim-validation` | 5x |
| `POST /v1/policies/compare` | 5x |
| `GET /v1/policies?mode=semantic` | 10x |
For example, if your rate limit is 60 requests/minute and you make a `policies/compare` request (5x cost), it counts as 5 requests against your limit.
Upgrading Your Plan [#upgrading-your-plan]
If you consistently hit rate limits, consider upgrading your plan:
* **Starter** ($149/mo): 100 req/min, 5,000 calls/month
* **Professional** ($499/mo): 300 req/min, 25,000 calls/month, FHIR output, semantic search
* **Enterprise** ($3,000+/mo): 1,000 req/min, 100,000 calls/month, webhooks, SSO
Visit the [Usage & Billing](/console/usage) page in the Developer Console to upgrade.
# Acknowledge a policy change
URL: /docs/api/acknowledgeChange
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Mark a single policy change as reviewed/acknowledged for the authenticated
organization. Idempotent — acknowledging an already-acked change returns 200.
Requires Professional plan or higher and an API key with `write` or `admin` scope.
# Batch code lookup
URL: /docs/api/batchLookupCodes
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Look up multiple medical codes in a single request. Returns results keyed by code.
Maximum 50 codes per request. Fuzzy matching is disabled in batch mode for performance.
**Partial failure handling:** Individual code lookup failures do not abort the batch.
A code that cannot be resolved returns `{"found": false, "code": "", "code_system": "UNKNOWN"}`
in the results map instead of causing a request-level error.
# Bulk acknowledge policy changes
URL: /docs/api/bulkAcknowledgeChanges
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Acknowledge multiple policy changes at once. Accepts up to 200 diff IDs.
Uses ON CONFLICT DO NOTHING for idempotency.
Requires Professional plan or higher and an API key with `write` or `admin` scope.
# Check prior authorization requirements
URL: /docs/api/checkPriorAuth
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Evaluates if a procedure requires prior authorization based on
procedure codes, diagnosis codes, and state/jurisdiction.
Returns matched policies, documentation requirements, and criteria details.
# Compare policies across jurisdictions
URL: /docs/api/comparePolicies
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Compare coverage policies across different MAC jurisdictions for the same procedure codes.
Separates national vs. jurisdiction-specific policies.
# Create webhook endpoint
URL: /docs/api/createWebhook
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Register a new webhook endpoint. The URL must use HTTPS and must resolve to a
public IP address. URLs pointing to private IP ranges (RFC 1918), loopback addresses,
or link-local addresses are rejected to prevent SSRF attacks.
Requires an API key with `write` or `admin` scope.
The secret is returned only once on creation — store it securely.
Event types: `policy.created`, `policy.updated`, `policy.retired`, `policy.codes_changed`, `policy.criteria_changed`, or `*` for all.
# Delete webhook endpoint
URL: /docs/api/deleteWebhook
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Soft-delete a webhook endpoint. It will no longer receive deliveries. Requires an API key with `write` or `admin` scope.
# Evaluate coverage criteria
URL: /docs/api/evaluateCoverage
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Evaluate a policy's structured coverage criteria (logic AST) against provided patient/claim parameters.
Returns whether coverage criteria are met, confidence score, and detailed reasons.
Requires Professional plan or higher.
# Get compliance statistics
URL: /docs/api/getComplianceStats
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Returns compliance dashboard statistics for the authenticated organization,
including total changes, acknowledgment count, acknowledgment rate, and
critical unreviewed count for the last 30 days.
Requires Professional plan or higher.
# Health check
URL: /docs/api/getHealth
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Public endpoint for monitoring API health status.
Returns database and Redis connectivity checks.
Used for load balancer health checks.
# Get policy by ID
URL: /docs/api/getPolicy
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Get a single policy by ID with optional related data.
Use the include parameter to fetch criteria, codes, attachments, or version history.
# Get policy change feed
URL: /docs/api/getPolicyChanges
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Track policy updates and modifications over time.
Useful for monitoring policy changes and keeping systems in sync.
# Get prior authorization research status
URL: /docs/api/getPriorAuthResearch
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Poll the status and results of a prior authorization research task.
Returns the current status, and when completed, the full structured
research results. No cost for polling.
# Get Medicaid spending by code
URL: /docs/api/getSpendingByCode
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Returns aggregate Medicaid provider spending statistics per HCPCS code,
including totals and year-over-year breakdowns from CMS claims data.
# API Reference
URL: /docs/api
Complete reference for the Verity REST API. All endpoints are prefixed with https://verity.backworkai.com/api/v1.
The Verity API is a REST API that returns JSON. All endpoints require an API key passed as a Bearer token.
```bash
Authorization: Bearer vrt_live_YOUR_API_KEY
```
Get your key at [verity.backworkai.com/keys](https://verity.backworkai.com/keys). See [Authentication](/docs/authentication) for key types and scopes.
Infrastructure [#infrastructure]
Policies [#policies]
Code Lookup [#code-lookup]
Coverage & Prior Auth [#coverage--prior-auth]
Agent Tools [#agent-tools]
Webhooks [#webhooks]
Policy Change Compliance [#policy-change-compliance]
# Invoke agent tool
URL: /docs/api/invokeAgentTool
Invokes one high-level Verity tool through the controlled agent access layer. Use `GET /agent/tools` first to fetch the exact input schema for each tool.
Use `response_format: "concise"` for normal agent reasoning and `response_format: "detailed"` when the agent needs source metadata, code lists, or audit evidence. Policy search uses `search_query`, not a generic `query` field.
Write tools such as `acknowledge_policy_change` return `202` with `approval_status: "required"` unless the caller includes `X-Verity-Approval: reviewed` after authorized human or operator review. Read the response `result_window` fields before assuming a list is complete.
# List agent tools
URL: /docs/api/listAgentTools
Returns the machine-readable tool catalog for controlled agent access, including input schemas, required scopes, approval posture, and whether the authenticated key can invoke each tool.
The manifest is the progressive-disclosure entry point for agents. It includes tool descriptions, MCP-style annotations, input schemas, and scope hints so the agent can choose the smallest safe tool before invoking it.
# List MAC jurisdictions
URL: /docs/api/listJurisdictions
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Returns list of Medicare Administrative Contractor (MAC) jurisdictions.
Cached for 24 hours since this is static reference data.
# Search and list policies
URL: /docs/api/listPolicies
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Search and list coverage policies with filtering and pagination.
Supports keyword and semantic search modes.
# List unreviewed policy changes
URL: /docs/api/listUnreviewedChanges
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Returns policy changes from the last 30 days that have not been acknowledged
by the authenticated organization. Supports cursor-based pagination.
Requires Professional plan or higher.
# List webhook endpoints
URL: /docs/api/listWebhooks
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
List all webhook endpoints for your organization. Requires Enterprise plan.
# Look up a medical code
URL: /docs/api/lookupCode
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Looks up medical codes (CPT, HCPCS, ICD-10, NDC) and returns coverage information.
When exact match fails and fuzzy is enabled, returns suggestions based on code
similarity and description matching.
# Research prior authorization requirements
URL: /docs/api/researchPriorAuth
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Use AI-powered web research to find prior authorization requirements
directly from payer websites. Supports async mode (returns research\_id
for polling) or synchronous mode (waits for completion).
Cost: 5 billable units per request.
# Search coverage criteria
URL: /docs/api/searchCriteria
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Search through coverage criteria blocks (indications, limitations, documentation requirements)
across policies.
# Search drug formulary evidence
URL: /docs/api/searchDrugFormularyEvidence
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Search commercial pharmacy-benefit evidence from CVS Caremark, Express Scripts, and UnitedHealthcare / Optum Rx.
# Send test webhook
URL: /docs/api/testWebhook
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Send a `test.ping` event to the webhook endpoint to verify it's reachable and
correctly validating signatures. The endpoint URL is validated for SSRF before
delivery — URLs resolving to private IP ranges will return an error.
Requires an API key with `write` or `admin` scope.
# Update webhook endpoint
URL: /docs/api/updateWebhook
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Update a webhook endpoint's URL, events, or status. Requires an API key with `write` or `admin` scope.
# Validate claim coverage risk
URL: /docs/api/validateClaim
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Run a rule-level, non-PHI pre-submission validation for CPT/HCPCS
procedure codes and optional ICD-10 diagnosis/context fields.
Returns coverage status, prior-auth requirement, denial risk, and
issues that should be resolved before authorization or claim submission.
# Validate coverage and denial risk
URL: /docs/api/validateClaims
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
Run a rule-level, non-PHI pre-submission validation for CPT/HCPCS
procedure codes, diagnosis codes, payer context, prior-auth requirements,
documentation requirements, and denial risk.
# .NET SDK
URL: /docs/sdks/dotnet
Official Verity SDK for C# and .NET with async/await support
The official Verity .NET SDK provides a strongly-typed way to integrate Medicare coverage intelligence into your C#, F#, and .NET applications.
Installation [#installation]
Install via NuGet Package Manager:
```bash
dotnet add package Verity.SDK
```
Or via Package Manager Console in Visual Studio:
```powershell
Install-Package Verity.SDK
```
**Requirements**: .NET Standard 2.0+ (.NET Framework 4.6.1+, .NET Core 2.0+, .NET 5+)
Quick Start [#quick-start]
```csharp
using Verity;
// Initialize the client
var client = new VerityClient("vrt_live_YOUR_API_KEY");
// Make your first request
var health = await client.HealthAsync();
Console.WriteLine(health.Data.Status); // "healthy"
```
Authentication [#authentication]
Set your API key when initializing the client:
```csharp
using Verity;
// Option 1: Pass directly
var client = new VerityClient("vrt_live_YOUR_API_KEY");
// Option 2: With configuration
var client = new VerityClient(new VerityClientOptions
{
ApiKey = "vrt_live_YOUR_API_KEY",
BaseUrl = "https://verity.backworkai.com/api/v1", // optional
Timeout = TimeSpan.FromSeconds(30) // optional
});
// Option 3: From configuration
var apiKey = Configuration["Verity:ApiKey"];
var client = new VerityClient(apiKey);
```
Get your API key from the [Developer Console](/console/keys).
Common Use Cases [#common-use-cases]
Check if a Procedure Needs Prior Authorization [#check-if-a-procedure-needs-prior-authorization]
```csharp
using Verity;
using System;
using System.Linq;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// Check for a knee replacement in Texas
var request = new PriorAuthRequest
{
ProcedureCodes = new[] { "27447" }, // Total knee replacement
DiagnosisCodes = new[] { "M17.11" }, // Unilateral primary osteoarthritis, right knee
State = "TX"
};
var result = await client.CheckPriorAuthAsync(request);
if (result.Data.PaRequired)
{
Console.WriteLine("Warning: Prior authorization required!");
Console.WriteLine($"Confidence: {result.Data.Confidence}");
Console.WriteLine($"Reason: {result.Data.Reason}");
// Show what documentation is needed
Console.WriteLine("\nDocumentation checklist:");
foreach (var item in result.Data.DocumentationChecklist ?? Enumerable.Empty())
{
Console.WriteLine($" • {item}");
}
// Show matched policies
Console.WriteLine($"\nMatched {result.Data.MatchedPolicies?.Count ?? 0} policies:");
foreach (var policy in result.Data.MatchedPolicies?.Take(3) ?? Enumerable.Empty())
{
Console.WriteLine($" • {policy.PolicyId}: {policy.Title}");
}
}
else
{
Console.WriteLine("No prior authorization needed");
}
```
Look Up Procedure Code with Coverage Info [#look-up-procedure-code-with-coverage-info]
```csharp
using Verity;
using System;
using System.Linq;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// Look up a code with RVU data and policies
var request = new CodeLookupRequest
{
Code = "76942", // Ultrasound guidance
Include = new[] { "rvu", "policies" }
};
var result = await client.LookupCodeAsync(request);
var codeData = result.Data;
Console.WriteLine($"Code: {codeData.Code}");
Console.WriteLine($"Description: {codeData.Description}");
// Show reimbursement info
if (codeData.Rvu != null)
{
Console.WriteLine("\nReimbursement (2026):");
Console.WriteLine($" Work RVU: {codeData.Rvu.WorkRvu}");
Console.WriteLine($" Facility price: ${codeData.Rvu.FacilityPrice}");
Console.WriteLine($" Non-facility price: ${codeData.Rvu.NonFacilityPrice}");
}
// Show coverage policies
if (codeData.Policies != null)
{
Console.WriteLine($"\nFound {codeData.Policies.Count} coverage policies:");
foreach (var policy in codeData.Policies.Take(5))
{
Console.WriteLine($" • [{policy.Disposition}] {policy.Title}");
}
}
```
Search Coverage Policies by Keyword [#search-coverage-policies-by-keyword]
```csharp
using Verity;
using System;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// Search for policies about diabetes CGM devices
var request = new PolicySearchRequest
{
Query = "continuous glucose monitoring diabetes",
PolicyType = "LCD", // Local Coverage Determinations
Status = PolicyStatus.Active,
Limit = 10
};
var result = await client.ListPoliciesAsync(request);
Console.WriteLine($"Found {result.Data.Count} active LCDs about CGM:\n");
foreach (var policy in result.Data)
{
Console.WriteLine($"Policy: {policy.PolicyId}");
Console.WriteLine($"Title: {policy.Title}");
Console.WriteLine($"Jurisdiction: {policy.Jurisdiction ?? "National"}");
Console.WriteLine($"Effective: {policy.EffectiveDate?.ToString("yyyy-MM-dd") ?? "N/A"}");
Console.WriteLine("---");
}
```
Compare Coverage Across Jurisdictions [#compare-coverage-across-jurisdictions]
```csharp
using Verity;
using System;
using System.Linq;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// Compare ultrasound guidance coverage across different MACs
var request = new ComparePoliciesRequest
{
ProcedureCodes = new[] { "76942" },
Jurisdictions = new[] { "J05", "J06", "J12", "JM" } // Different MAC jurisdictions
};
var result = await client.ComparePoliciesAsync(request);
var comparison = result.Data.Comparison;
Console.WriteLine("Coverage comparison across jurisdictions:\n");
foreach (var juris in comparison ?? Enumerable.Empty())
{
Console.WriteLine($"{juris.Jurisdiction} ({juris.MacName}):");
Console.WriteLine($" States: {string.Join(", ", juris.States ?? Enumerable.Empty())}");
Console.WriteLine($" Policies: {juris.Policies?.Count ?? 0}");
foreach (var policy in juris.Policies ?? Enumerable.Empty())
{
Console.WriteLine($" • {policy.PolicyId}: {policy.Disposition}");
}
Console.WriteLine();
}
```
Monitor Policy Changes [#monitor-policy-changes]
```csharp
using Verity;
using System;
using System.Linq;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// Get policies updated in the last 7 days
var sevenDaysAgo = DateTime.UtcNow.AddDays(-7);
var request = new PolicyChangesRequest
{
Since = sevenDaysAgo,
ChangeType = "updated",
Limit = 20
};
var result = await client.GetPolicyChangesAsync(request);
Console.WriteLine("Policy changes in the last 7 days:\n");
foreach (var change in result.Data)
{
Console.WriteLine($"Policy: {change.PolicyId}");
Console.WriteLine($"Change: {change.ChangeType}");
Console.WriteLine($"Summary: {change.ChangeSummary ?? "No summary"}");
Console.WriteLine($"Timestamp: {change.Timestamp}");
Console.WriteLine("---");
}
```
Get Detailed Policy Information [#get-detailed-policy-information]
```csharp
using Verity;
using System;
using System.Linq;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// Get full policy details with criteria
var result = await client.GetPolicyAsync("L33831", new GetPolicyRequest
{
Include = new[] { "criteria", "codes", "attachments" }
});
var policy = result.Data;
Console.WriteLine($"Policy: {policy.Title}");
Console.WriteLine($"Type: {policy.PolicyType}");
Console.WriteLine($"Status: {policy.Status}");
Console.WriteLine($"Effective: {policy.EffectiveDate?.ToString("yyyy-MM-dd") ?? "N/A"}");
// Show coverage criteria
if (policy.Criteria != null)
{
Console.WriteLine("\nCoverage Criteria:");
foreach (var section in policy.Criteria)
{
Console.WriteLine($"\n{section.Key.ToUpper()}:");
foreach (var block in section.Value.Take(3)) // Show first 3
{
Console.WriteLine($" • {block.Text?.Substring(0, Math.Min(100, block.Text.Length ?? 0))}...");
}
}
}
// Show covered codes
if (policy.Codes != null)
{
Console.WriteLine($"\nCovers {policy.Codes.Count} codes");
foreach (var code in policy.Codes.Take(10))
{
Console.WriteLine($" • {code.Code} ({code.CodeSystem}): {code.Disposition}");
}
}
```
Search Coverage Criteria [#search-coverage-criteria]
```csharp
using Verity;
using System;
using System.Linq;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// Search for specific coverage criteria about BMI requirements
var request = new CriteriaSearchRequest
{
Query = "BMI greater than 40",
Section = CriteriaSection.Indications,
PolicyType = "LCD",
Limit = 10
};
var result = await client.SearchCriteriaAsync(request);
Console.WriteLine("BMI-related coverage criteria:\n");
foreach (var criteria in result.Data)
{
Console.WriteLine($"Policy: {criteria.PolicyId}");
Console.WriteLine($"Section: {criteria.Section}");
Console.WriteLine($"Text: {criteria.Text?.Substring(0, Math.Min(200, criteria.Text.Length ?? 0))}...");
Console.WriteLine($"Tags: {string.Join(", ", criteria.Tags ?? Enumerable.Empty())}");
Console.WriteLine("---");
}
```
List MAC Jurisdictions [#list-mac-jurisdictions]
```csharp
using Verity;
using System;
using System.Linq;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
var result = await client.ListJurisdictionsAsync();
Console.WriteLine("Medicare Administrative Contractors (MACs):\n");
foreach (var jurisdiction in result.Data)
{
Console.WriteLine($"{jurisdiction.JurisdictionCode}: {jurisdiction.MacName}");
Console.WriteLine($" States: {string.Join(", ", jurisdiction.States ?? Enumerable.Empty())}");
Console.WriteLine($" Type: {jurisdiction.MacType ?? "N/A"}");
Console.WriteLine();
}
```
Research Prior Auth with AI Web Search [#research-prior-auth-with-ai-web-search]
```csharp
using Verity;
using System;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// Async mode (default) - returns research_id for polling
var research = await client.ResearchPriorAuthAsync(
procedureCodes: new[] { "27447" },
payer: "UnitedHealthcare",
state: "TX"
);
var researchId = research.Data.ResearchId;
Console.WriteLine($"Research started: {researchId}");
// Poll for results
PriorAuthResearchResult status;
do
{
await Task.Delay(2000);
var poll = await client.GetPriorAuthResearchAsync(researchId);
status = poll.Data;
} while (status.Status != "completed" && status.Status != "failed");
if (status.Status == "completed")
{
Console.WriteLine($"Results: {status.Result}");
}
// Or use sync mode to wait for completion
var syncResult = await client.ResearchPriorAuthAsync(
procedureCodes: new[] { "27447" },
payer: "Aetna",
state: "CA",
sync: true
);
```
Get Medicaid Spending Data [#get-medicaid-spending-data]
```csharp
using Verity;
using System;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// Single code
var result = await client.GetSpendingByCodeAsync(code: "T1019");
var spending = result.Data["T1019"];
Console.WriteLine($"Total paid: ${spending.TotalPaid}");
Console.WriteLine($"Total claims: {spending.TotalClaims}");
foreach (var year in spending.ByYear)
{
Console.WriteLine($" {year.Year}: ${year.TotalPaid} ({year.TotalClaims} claims)");
}
// Multiple codes with year filter
var multi = await client.GetSpendingByCodeAsync(
codes: new[] { "T1019", "T1020" },
year: 2023
);
```
ASP.NET Core Integration [#aspnet-core-integration]
Dependency Injection Setup [#dependency-injection-setup]
```csharp
// Startup.cs or Program.cs
using Microsoft.Extensions.DependencyInjection;
using Verity;
public void ConfigureServices(IServiceCollection services)
{
// Add Verity client as a singleton
services.AddSingleton(sp =>
{
var apiKey = Configuration["Verity:ApiKey"];
return new VerityClient(apiKey);
});
services.AddControllers();
}
```
Using in a Controller [#using-in-a-controller]
```csharp
using Microsoft.AspNetCore.Mvc;
using Verity;
using System.Threading.Tasks;
[ApiController]
[Route("api/[controller]")]
public class CodesController : ControllerBase
{
private readonly IVerityClient _verity;
public CodesController(IVerityClient verity)
{
_verity = verity;
}
[HttpGet("{code}")]
public async Task GetCode(string code)
{
try
{
var result = await _verity.LookupCodeAsync(new CodeLookupRequest
{
Code = code,
Include = new[] { "rvu", "policies" }
});
return Ok(result);
}
catch (VerityAuthenticationException ex)
{
return Unauthorized(new { error = ex.Message });
}
catch (VerityValidationException ex)
{
return BadRequest(new { error = ex.Message, details = ex.Details });
}
catch (VerityException ex)
{
return StatusCode(500, new { error = ex.Message });
}
}
}
```
Error Handling [#error-handling]
The SDK provides structured exceptions for different error types:
```csharp
using Verity;
using System;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
try
{
var result = await client.LookupCodeAsync(new CodeLookupRequest { Code = "INVALID" });
}
catch (VerityAuthenticationException ex)
{
Console.WriteLine($"Invalid API key: {ex.Message}");
}
catch (VerityValidationException ex)
{
Console.WriteLine($"Invalid parameters: {ex.Message}");
if (ex.Details != null)
{
Console.WriteLine($"Details: {string.Join(", ", ex.Details)}");
}
}
catch (VerityNotFoundException ex)
{
Console.WriteLine($"Resource not found: {ex.Message}");
}
catch (VerityRateLimitException ex)
{
Console.WriteLine($"Rate limit exceeded. Resets at: {ex.ResetAt}");
Console.WriteLine($"Limit: {ex.Limit}, Remaining: {ex.Remaining}");
}
catch (VerityException ex)
{
Console.WriteLine($"API error: {ex.Message} (code: {ex.Code})");
if (!string.IsNullOrEmpty(ex.Hint))
{
Console.WriteLine($"Hint: {ex.Hint}");
}
}
```
Response Format [#response-format]
All methods return strongly-typed responses:
```csharp
public class ApiResponse
{
public bool Success { get; set; }
public T Data { get; set; }
public ApiMeta Meta { get; set; }
}
public class ApiMeta
{
public string RequestId { get; set; }
public DateTime Timestamp { get; set; }
// Additional metadata...
}
```
Async/Await Patterns [#asyncawait-patterns]
All SDK methods are async and follow TAP (Task-based Asynchronous Pattern):
```csharp
using Verity;
using System;
using System.Threading;
using System.Threading.Tasks;
var client = new VerityClient(Environment.GetEnvironmentVariable("VERITY_API_KEY"));
// With cancellation token
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
try
{
var result = await client.LookupCodeAsync(
new CodeLookupRequest { Code = "76942" },
cts.Token
);
}
catch (OperationCanceledException)
{
Console.WriteLine("Request cancelled or timed out");
}
```
Configuration Options [#configuration-options]
```csharp
using Verity;
using System;
using System.Net.Http;
var options = new VerityClientOptions
{
ApiKey = "vrt_live_YOUR_API_KEY",
BaseUrl = "https://verity.backworkai.com/api/v1",
Timeout = TimeSpan.FromSeconds(60),
// Custom HTTP client for advanced scenarios
HttpClient = new HttpClient
{
Timeout = TimeSpan.FromMinutes(2)
},
// Enable automatic retries (default: 3)
MaxRetries = 3,
// Retry delay (exponential backoff)
RetryDelay = TimeSpan.FromSeconds(1)
};
var client = new VerityClient(options);
```
Resources [#resources]
* **NuGet**: [Verity.SDK](https://www.nuget.org/packages/Verity.SDK/)
* **GitHub**: [backworkai/verity-dotnet](https://github.com/backworkai/verity-dotnet)
* **API Reference**: [All Endpoints](/docs/api)
* **Issues**: [Report a bug](https://github.com/backworkai/verity-dotnet/issues)
Next Steps [#next-steps]
# Go CLI
URL: /docs/sdks/go
Command-line tool for Verity with single binary distribution
The Verity CLI is a powerful command-line tool for interacting with the Verity API. Perfect for DevOps workflows, automation scripts, and quick lookups from the terminal.
Installation [#installation]
Install from Source [#install-from-source]
```bash
git clone https://github.com/backworkai/verity-cli.git
cd verity-cli
go mod tidy
go build -o verity .
sudo mv verity /usr/local/bin/
```
Download Binary [#download-binary]
Pre-built binaries will be available from [GitHub Releases](https://github.com/backworkai/verity-cli/releases) once release assets are published.
Quick Start [#quick-start]
Set your API key as an environment variable:
```bash
export VERITY_API_KEY=vrt_live_YOUR_API_KEY
```
Or pass it with each command:
```bash
verity --api-key vrt_live_YOUR_API_KEY check 76942
```
Get your API key from the [Developer Console](/console/keys).
Common Use Cases [#common-use-cases]
Check if a Procedure Needs Prior Authorization [#check-if-a-procedure-needs-prior-authorization]
```bash
# Basic prior auth check
verity prior-auth 27447 --state TX
# With diagnosis codes
verity prior-auth 27447 --diagnosis M17.11 --state TX
# Multiple procedure codes
verity prior-auth 27447 76942 --state CA
# JSON output for scripting
verity prior-auth 27447 --state TX --output json | jq '.data.pa_required'
```
**Output:**
```
Prior Authorization Required: true
Confidence: high
Reason: Procedure requires prior authorization in Texas
Matched Policies:
• L33831: Ultrasound Guidance for Needle Placement
• L38942: Diagnostic Ultrasound
Documentation Checklist:
• Medical necessity documentation
• Prior imaging results
• Conservative treatment history
```
Look Up Procedure Code with Coverage Info [#look-up-procedure-code-with-coverage-info]
```bash
# Basic code lookup
verity check 76942
# With RVU reimbursement data
verity check 76942 --rvu
# With coverage policies
verity check 76942 --policies
# Everything (RVU + policies)
verity check 76942 --rvu --policies
# Filter by jurisdiction
verity check 76942 --jurisdiction JM
```
**Output:**
```
Code: 76942
System: HCPCS
Found: true
Description: Echo guide for biopsy
RVU Data (2026):
Work RVU: 0.65
Facility Price: $64.13
Non-Facility Price: $64.13
Coverage Policies (16 found):
• [covered] Billing and Coding: Varicose Veins
• [covered] Billing and Coding: Nerve Blockade
• [not_covered] Ultrasound Guidance for Trigger Point Injections
```
Search Coverage Policies [#search-coverage-policies]
```bash
# Keyword search
verity policies list --query "ultrasound guidance"
# Filter by policy type
verity policies list --query "diabetes" --type LCD
# Filter by jurisdiction
verity policies list --query "CGM" --jurisdiction JM
# Active policies only
verity policies list --query "surgery" --status active
# JSON output
verity policies list --query "ultrasound" --output json | jq '.data[].policy_id'
```
**Output:**
```
Found 50 policies:
ID: A57305
Title: Billing and Coding: Varicose Veins of the Lower Extremity
Type: Article
Jurisdiction: JM
Status: active
---
ID: L33831
Title: Ultrasound Guidance for Needle Placement
Type: LCD
Jurisdiction: J06
Status: active
---
```
Get Detailed Policy Information [#get-detailed-policy-information]
```bash
# Get policy by ID
verity policies get L33831
# JSON output for parsing
verity policies get L33831 --output json | jq '.data.title'
```
**Output:**
```
Policy: L33831
Title: Ultrasound Guidance for Needle Placement
Type: LCD
Status: active
Jurisdiction: J06
Effective Date: 2024-01-01
Description:
This LCD outlines coverage requirements for ultrasound guidance
used during needle placement procedures...
Covered Codes (12):
• 76942 (HCPCS): covered
• 76998 (HCPCS): covered
```
List MAC Jurisdictions [#list-mac-jurisdictions]
```bash
# List all jurisdictions
verity jurisdictions
# JSON output
verity jurisdictions --output json
```
**Output:**
```
Medicare Administrative Contractors (MACs):
JM: Palmetto GBA
States: TX, OK, NM, CO, LA, AR, MS
J05: Novitas Solutions
States: PA, NJ, DE, MD, DC, WV
J06: National Government Services
States: IL, MN, WI
```
Research Prior Auth with AI Web Search [#research-prior-auth-with-ai-web-search]
```bash
# Async mode - returns research ID for polling
verity prior-auth research 27447 --payer "UnitedHealthcare" --state TX
# Output:
# Research ID: res_abc123
# Status: pending
# Poll URL: /api/v1/prior-auth/research/res_abc123
#
# Use 'verity prior-auth research-status ' to check progress
# Check research status
verity prior-auth research-status res_abc123
# Sync mode - waits for completion
verity prior-auth research 27447 --payer "Aetna" --state CA --sync
# JSON output
verity prior-auth research 27447 --payer "UnitedHealthcare" --sync --output json | jq '.data.result.determination'
```
Get Medicaid Spending Data [#get-medicaid-spending-data]
```bash
# Single code
verity spending T1019
# Multiple codes
verity spending T1019 T1020
# Filter by year
verity spending T1019 --year 2023
# JSON output for scripting
verity spending T1019 --output json | jq '.data.T1019.total_paid'
```
Check API Health [#check-api-health]
```bash
verity health
# Output:
# Status: healthy
# Version: 1.0.0
# Timestamp: 2026-02-17T12:00:00Z
#
# Checks:
# database: healthy
# redis: healthy
```
Search Coverage Criteria [#search-coverage-criteria]
```bash
# Search criteria text
verity coverage search "BMI greater than 40"
# Filter by section and policy type
verity coverage search "conservative treatment" --section indications --type LCD
# Filter by jurisdiction
verity coverage search "frequency limits" --jurisdiction JM
# JSON output
verity coverage search "BMI" --output json | jq '.data[].text'
```
Compare Policies Across Jurisdictions [#compare-policies-across-jurisdictions]
```bash
# Compare coverage for a procedure
verity policies compare 76942
# Compare specific jurisdictions
verity policies compare 76942 --jurisdictions J05,J06,JM
# Multiple codes with policy type filter
verity policies compare 27447 76942 --type LCD
# JSON output
verity policies compare 76942 --output json | jq '.data.comparison'
```
Scripting & Automation [#scripting--automation]
Check Multiple Codes in a Loop [#check-multiple-codes-in-a-loop]
```bash
#!/bin/bash
CODES=("76942" "27447" "99213" "J0585")
for code in "${CODES[@]}"; do
echo "Checking $code..."
verity check "$code" --output json | jq -r '.data.description'
done
```
Monitor for Policy Changes [#monitor-for-policy-changes]
```bash
#!/bin/bash
# Get changes from the last 24 hours
SINCE=$(date -u -v-24H +"%Y-%m-%dT%H:%M:%SZ") # macOS
# SINCE=$(date -u -d '24 hours ago' +"%Y-%m-%dT%H:%M:%SZ") # Linux
verity policies changes --since "$SINCE" --output json | \
jq -r '.data[] | "\(.policy_id): \(.change_type) - \(.change_summary)"'
```
Pre-submission Prior Auth Check [#pre-submission-prior-auth-check]
```bash
#!/bin/bash
# Check if procedures need PA before submitting claim
PROCEDURES=("27447" "76942")
DIAGNOSES=("M17.11" "M79.3")
STATE="TX"
result=$(verity prior-auth "${PROCEDURES[@]}" \
--diagnosis "${DIAGNOSES[@]}" \
--state "$STATE" \
--output json)
pa_required=$(echo "$result" | jq -r '.data.pa_required')
if [ "$pa_required" = "true" ]; then
echo "Warning: Prior authorization required!"
echo "$result" | jq -r '.data.documentation_checklist[]'
exit 1
else
echo "No prior authorization needed"
exit 0
fi
```
Export Policy Data to CSV [#export-policy-data-to-csv]
```bash
#!/bin/bash
# Search and export to CSV
verity policies list --query "diabetes" --output json | \
jq -r '.data[] | [.policy_id, .title, .policy_type, .status] | @csv' > policies.csv
```
Output Formats [#output-formats]
The CLI supports multiple output formats:
```bash
# Table (default) - human-readable
verity check 76942
# JSON - for scripting
verity check 76942 --output json
# YAML - for configuration
verity check 76942 --output yaml
```
Configuration File [#configuration-file]
Save your API key and preferences in a config file:
```bash
# Create config file
mkdir -p ~/.verity
cat > ~/.verity/config.yaml << EOF
api-key: vrt_live_YOUR_API_KEY
base-url: https://verity.backworkai.com/api/v1
output: table
EOF
# Now you can use the CLI without --api-key
verity check 76942
```
Global Flags [#global-flags]
Available for all commands:
```bash
--api-key string # Verity API key (or set VERITY_API_KEY env var)
--base-url string # API base URL (default: https://verity.backworkai.com/api/v1)
--output string # Output format: table, json, yaml (default: table)
--config string # Config file (default: $HOME/.verity/config.yaml)
```
All Commands [#all-commands]
verity check [#verity-check-code]
Look up a medical code.
**Flags:**
* `--jurisdiction ` - Filter by MAC jurisdiction
* `--rvu` - Include RVU data
* `--policies` - Include policy information
**Example:**
```bash
verity check 76942 --rvu --policies --jurisdiction JM
```
verity health [#verity-health]
Check API health status.
**Example:**
```bash
verity health
```
verity prior-auth [#verity-prior-auth-codes]
Check prior authorization requirements.
**Flags:**
* `--diagnosis ` - Diagnosis codes (ICD-10)
* `--state ` - Two-letter state code
* `--payer ` - Payer (medicare, aetna, uhc, all)
**Example:**
```bash
verity prior-auth 27447 76942 --diagnosis M17.11 --state TX
```
verity prior-auth research [#verity-prior-auth-research-codes]
Research prior auth requirements via AI web search.
**Flags:**
* `--payer ` - Payer name (e.g., UnitedHealthcare, Aetna)
* `--state ` - Two-letter state code
* `--diagnosis ` - Diagnosis codes (ICD-10)
* `--context ` - Additional clinical context
* `--sync` - Wait for completion
**Example:**
```bash
verity prior-auth research 27447 --payer "UnitedHealthcare" --state TX --sync
```
verity prior-auth research-status [#verity-prior-auth-research-status-research-id]
Poll the status of a prior auth research task.
**Example:**
```bash
verity prior-auth research-status res_abc123
```
verity policies list [#verity-policies-list]
Search and list policies.
**Flags:**
* `--query ` - Search query
* `--type ` - Policy type (LCD, Article, NCD)
* `--jurisdiction ` - MAC jurisdiction
* `--status ` - Status (active, retired, all)
* `--mode ` - Search mode (keyword, semantic)
**Example:**
```bash
verity policies list --query "ultrasound" --type LCD --status active
```
verity policies get [#verity-policies-get-policy-id]
Get detailed policy information.
**Example:**
```bash
verity policies get L33831
```
verity policies changes [#verity-policies-changes]
Get policy change feed.
**Flags:**
* `--since ` - ISO 8601 timestamp
* `--policy-id ` - Filter by policy ID
* `--change-type ` - Change type filter
**Example:**
```bash
verity policies changes --since 2026-01-01T00:00:00Z
```
verity policies compare [#verity-policies-compare-codes]
Compare policies across jurisdictions.
**Flags:**
* `--type ` - Policy type (LCD, Article, NCD)
* `--jurisdictions ` - Specific jurisdictions to compare
**Example:**
```bash
verity policies compare 76942 --jurisdictions J05,J06,JM
```
verity jurisdictions [#verity-jurisdictions]
List all MAC jurisdictions.
**Example:**
```bash
verity jurisdictions
```
verity coverage search [#verity-coverage-search-query]
Search coverage criteria text across policies.
**Flags:**
* `--section ` - Filter by section (indications, limitations, documentation)
* `--type ` - Policy type (LCD, Article, NCD)
* `--jurisdiction ` - MAC jurisdiction
* `--limit ` - Results per page (1-100)
**Example:**
```bash
verity coverage search "BMI greater than 40" --section indications --type LCD
```
verity spending [#verity-spending-codes]
Get Medicaid spending data by HCPCS code.
**Flags:**
* `--year ` - Filter to a specific year
**Example:**
```bash
verity spending T1019 T1020 --year 2023
```
Shell Completion [#shell-completion]
Generate shell completion scripts:
```bash
# Bash
verity completion bash > /usr/local/etc/bash_completion.d/verity
# Zsh
verity completion zsh > /usr/local/share/zsh/site-functions/_verity
# Fish
verity completion fish > ~/.config/fish/completions/verity.fish
# PowerShell
verity completion powershell | Out-String | Invoke-Expression
```
Building from Source [#building-from-source]
```bash
git clone https://github.com/backworkai/verity-cli.git
cd verity-cli
go mod tidy
go build -o verity .
./verity --help
```
**Build for all platforms:**
```bash
make build-all
# Creates binaries in dist/ for:
# - darwin/amd64, darwin/arm64
# - linux/amd64, linux/arm64
# - windows/amd64
```
Resources [#resources]
* **GitHub**: [backworkai/verity-cli](https://github.com/backworkai/verity-cli)
* **Releases**: [Download Binaries](https://github.com/backworkai/verity-cli/releases)
* **API Reference**: [All Endpoints](/docs/api)
* **Issues**: [Report a bug](https://github.com/backworkai/verity-cli/issues)
Next Steps [#next-steps]
# SDKs & Libraries
URL: /docs/sdks
Official SDKs and tools for integrating Verity into your application
Build with Verity using our official SDKs for popular languages and platforms.
Server-Side SDKs [#server-side-sdks]
Command Line [#command-line]
Community SDKs [#community-sdks]
Don't see your language? We'd love your help building a community SDK. Check out the [API reference](/docs/api) to get started.
Features [#features]
All official SDKs include:
* **Full API Coverage** - All endpoints, parameters, and response types
* **Type Safety** - Complete type definitions and IntelliSense support
* **Error Handling** - Structured errors with helpful messages
* **Automatic Retries** - Built-in exponential backoff for transient failures
* **Modern Async** - Promise/async/await patterns throughout
* **Well Documented** - Comprehensive guides and code examples
Installation Quick Links [#installation-quick-links]
```bash
pip install verity-python
```
[View Python Docs →](/docs/sdks/python)
```bash
npm install verity-api
```
[View TypeScript Docs →](/docs/sdks/typescript)
```bash
git clone https://github.com/backworkai/verity-ruby.git
cd verity-ruby
bundle install
```
[View Ruby Docs →](/docs/sdks/ruby)
```bash
git clone https://github.com/backworkai/verity-cli.git
cd verity-cli
go mod tidy
go build -o verity .
sudo mv verity /usr/local/bin/
```
[View Go Docs →](/docs/sdks/go)
```bash
dotnet add package Verity.SDK
```
[View .NET Docs →](/docs/sdks/dotnet)
Need Help? [#need-help]
* **API Reference**: [All Endpoints](/docs/api)
* **Authentication**: [API Keys](/docs/authentication)
* **Support**: [support@verity.backworkai.com](mailto:support@verity.backworkai.com)
* **GitHub**: [Report an issue](https://github.com/backworkai)
# Python SDK
URL: /docs/sdks/python
Official Verity SDK for Python with type hints and modern async support
The Verity Python SDK gives you clean, typed access to Medicare coverage intelligence. Built for data science workflows and backend services.
Installation [#installation]
```bash
pip install verity-python
```
Requires Python 3.8+. Works with any HTTP client under the hood (uses httpx).
Quick start [#quick-start]
```python
from verity import VerityClient
client = VerityClient(api_key="vrt_live_YOUR_API_KEY")
# Make your first request
health = client.health()
print(health["data"]["status"]) # "healthy"
```
Get your API key from the [Developer Console](/console/keys).
Authentication [#authentication]
```python
from verity import VerityClient
import os
# Pass directly
client = VerityClient(api_key="vrt_live_YOUR_API_KEY")
# Or from environment
client = VerityClient(api_key=os.getenv("VERITY_API_KEY"))
# Custom base URL for testing
client = VerityClient(
api_key="vrt_live_YOUR_API_KEY",
base_url="https://staging.verity.backworkai.com/api/v1"
)
```
Common scenarios [#common-scenarios]
Check if a procedure needs prior auth [#check-if-a-procedure-needs-prior-auth]
Most prior auth checks fail because you don't know what documentation to include. The API tells you exactly what's required.
```python
result = client.check_prior_auth(
procedure_codes=["27447"], # Total knee replacement
diagnosis_codes=["M17.11"], # Unilateral primary osteoarthritis, right knee
state="TX"
)
if result["data"]["pa_required"]:
print(f"Warning: Prior authorization required")
print(f"Confidence: {result['data']['confidence']}")
print(f"Reason: {result['data']['reason']}")
# Show exact documentation requirements
print("\nYou need:")
for item in result["data"]["documentation_checklist"]:
print(f" • {item}")
# Show which policies triggered this
print(f"\nBased on {len(result['data']['matched_policies'])} policies:")
for policy in result["data"]["matched_policies"][:3]:
print(f" • {policy['policy_id']}: {policy['title']}")
```
**Output:**
```
Warning: Prior authorization required
Confidence: high
Reason: Procedure requires review of medical necessity
You need:
• X-ray documentation showing degenerative joint disease
• Conservative treatment history (6+ weeks)
• Functional assessment scores
• BMI documentation
Based on 8 policies:
• L33822: Total Knee Replacement
• A57305: Billing and Coding: Joint Replacement
```
The `confidence` field tells you how reliable this is. `high` means multiple policies agree. `low` means it's ambiguous or jurisdiction-dependent.
Look up codes with reimbursement data [#look-up-codes-with-reimbursement-data]
```python
result = client.lookup_code(
code="76942",
include=["rvu", "policies"]
)
code_data = result["data"]
print(f"{code_data['code']}: {code_data['description']}")
# RVU data is current year (2026)
if code_data.get("rvu"):
rvu = code_data["rvu"]
print(f"\nReimbursement:")
print(f" Work RVU: {rvu['work_rvu']}")
print(f" Facility: ${rvu['facility_price']}")
print(f" Non-facility: ${rvu['non_facility_price']}")
# Coverage policies show disposition by jurisdiction
if code_data.get("policies"):
print(f"\nCoverage: {len(code_data['policies'])} policies found")
covered = sum(1 for p in code_data["policies"] if p["disposition"] == "covered")
not_covered = sum(1 for p in code_data["policies"] if p["disposition"] == "not_covered")
print(f" Covered: {covered}")
print(f" Not covered: {not_covered}")
print(f" Conditional: {len(code_data['policies']) - covered - not_covered}")
```
Search policies by keyword or semantically [#search-policies-by-keyword-or-semantically]
```python
# Keyword search (fast, exact matches)
result = client.list_policies(
q="continuous glucose monitoring",
policy_type="LCD",
status="active",
limit=10
)
print(f"Found {len(result['data'])} active LCDs\n")
for policy in result["data"]:
print(f"{policy['policy_id']}: {policy['title']}")
print(f" Jurisdiction: {policy.get('jurisdiction', 'National')}")
print(f" Effective: {policy.get('effective_date', 'N/A')}")
```
Semantic search (slower but finds related concepts):
```python
result = client.list_policies(
q="devices that monitor blood sugar levels",
mode="semantic", # Uses embedding similarity
limit=10
)
```
Semantic search finds policies about CGM devices even though you didn't use the exact term. It's slower (\~2-3x) but more flexible.
Compare coverage across MACs [#compare-coverage-across-macs]
Medicare coverage isn't national. A procedure covered in Texas (JM) might not be covered in Pennsylvania (J05).
```python
result = client.compare_policies(
procedure_codes=["76942"],
jurisdictions=["J05", "J06", "J12", "JM"]
)
for juris in result["data"]["comparison"]:
print(f"\n{juris['jurisdiction']} - {juris['mac_name']}")
print(f"States: {', '.join(juris['states'])}")
print(f"Policies: {len(juris['policies'])}")
for policy in juris["policies"]:
print(f" • {policy['policy_id']}: {policy['disposition']}")
```
This shows you exactly where coverage differs. Useful for multi-state practices or national payers.
Monitor policy changes [#monitor-policy-changes]
Policies change constantly. New LCDs get published, existing ones get retired, criteria get updated.
```python
from datetime import datetime, timedelta
# Get changes from the last 7 days
seven_days_ago = (datetime.now() - timedelta(days=7)).isoformat() + "Z"
result = client.get_policy_changes(
since=seven_days_ago,
change_type="updated",
limit=20
)
print(f"Policy updates in the last 7 days: {len(result['data'])}\n")
for change in result["data"]:
print(f"{change['policy_id']}: {change['change_type']}")
print(f" {change.get('change_summary', 'No summary available')}")
print(f" {change['timestamp']}\n")
```
Use this to stay current without manually checking payer portals.
Get full policy details with criteria [#get-full-policy-details-with-criteria]
```python
result = client.get_policy(
policy_id="L33831",
include=["criteria", "codes", "attachments"]
)
policy = result["data"]
print(f"{policy['title']}")
print(f"Type: {policy['policy_type']} | Status: {policy['status']}")
print(f"Effective: {policy.get('effective_date', 'N/A')}\n")
# Coverage criteria are AI-extracted from the PDF
if policy.get("criteria"):
print("Coverage Criteria:")
for section, blocks in policy["criteria"].items():
print(f"\n{section.upper()}:")
for block in blocks[:3]:
print(f" • {block.get('text', '')[:100]}...")
# Show which codes this policy covers
if policy.get("codes"):
print(f"\nCovers {len(policy['codes'])} codes:")
for code in policy["codes"][:10]:
print(f" • {code['code']} ({code['code_system']}): {code['disposition']}")
```
The `criteria` field contains structured text blocks extracted from the policy PDF. They're tagged by section (indications, limitations, documentation, etc.) and searchable via the `/coverage/criteria` endpoint.
Search specific coverage criteria [#search-specific-coverage-criteria]
Sometimes you need to find policies with specific requirements (e.g., BMI cutoffs, frequency limits).
```python
result = client.search_criteria(
q="BMI greater than 40",
section="indications",
policy_type="LCD",
limit=10
)
print("Policies with BMI > 40 requirement:\n")
for criteria in result["data"]:
print(f"{criteria['policy_id']} ({criteria['section']})")
print(f" {criteria['text'][:150]}...")
print(f" Tags: {', '.join(criteria.get('tags', []))}\n")
```
This is useful for finding policies with specific clinical criteria without reading every LCD.
List MAC jurisdictions [#list-mac-jurisdictions]
```python
result = client.list_jurisdictions()
print("Medicare Administrative Contractors:\n")
for juris in result["data"]:
print(f"{juris['jurisdiction_code']}: {juris['mac_name']}")
print(f" States: {', '.join(juris.get('states', []))}")
print(f" Type: {juris.get('mac_type', 'N/A')}\n")
```
Research prior auth with AI web search [#research-prior-auth-with-ai-web-search]
For commercial payers or when you need real-time payer website intelligence:
```python
# Async mode (default) - returns research_id for polling
result = client.research_prior_auth(
procedure_codes=["27447"],
payer="UnitedHealthcare",
state="TX"
)
research_id = result["data"]["research_id"]
print(f"Research started: {research_id}")
# Poll for results
import time
while True:
status = client.get_prior_auth_research(research_id)
if status["data"]["status"] in ("completed", "failed"):
break
time.sleep(2)
if status["data"]["status"] == "completed":
determination = status["data"]["result"]["determination"]
print(f"PA Required: {determination['pa_required']}")
print(f"Reasoning: {determination['reasoning']}")
# Or use sync mode to wait for completion
result = client.research_prior_auth(
procedure_codes=["27447"],
payer="Aetna",
state="CA",
sync=True # Blocks until complete
)
print(result["data"]["result"]["determination"])
```
Get Medicaid spending data [#get-medicaid-spending-data]
```python
# Single code
result = client.get_spending_by_code(code="T1019")
spending = result["data"]["T1019"]
print(f"Total paid: ${spending['total_paid']}")
print(f"Total claims: {spending['total_claims']}")
for year in spending["by_year"]:
print(f" {year['year']}: ${year['total_paid']} ({year['total_claims']} claims)")
# Multiple codes with year filter
result = client.get_spending_by_code(codes=["T1019", "T1020"], year=2023)
```
Error handling [#error-handling]
The SDK raises structured exceptions. Catch them specifically, not just generic `Exception`.
```python
from verity import (
VerityClient,
VerityError,
AuthenticationError,
ValidationError,
NotFoundError,
RateLimitError
)
client = VerityClient(api_key="vrt_live_YOUR_API_KEY")
try:
result = client.lookup_code(code="INVALID")
except AuthenticationError:
print("Invalid API key")
except ValidationError as e:
print(f"Bad request: {e.message}")
if e.details:
print(f"Details: {e.details}")
except NotFoundError:
print("Code not found")
except RateLimitError as e:
print(f"Rate limited. Resets in {e.reset - time.time():.0f}s")
except VerityError as e:
print(f"API error: {e.message} (code: {e.code})")
```
Don't catch `VerityError` at the top level unless you're doing generic error handling. Catch specific exceptions first.
Response format [#response-format]
All methods return dictionaries matching this structure:
```python
{
"success": True,
"data": { ... }, # The actual response
"meta": {
"request_id": "req_...",
"timestamp": "2026-01-25T12:00:00Z"
}
}
```
Error responses:
```python
{
"success": False,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid parameter: code",
"hint": "Code must be a valid CPT, HCPCS, or ICD-10 code"
}
}
```
Type hints [#type-hints]
The SDK includes type hints for IDE autocomplete. Use them.
```python
from verity import VerityClient
from typing import Dict, Any
client = VerityClient(api_key="vrt_live_YOUR_API_KEY")
# Type checker knows what parameters are valid
result: Dict[str, Any] = client.lookup_code(
code="76942",
include=["rvu", "policies"], # IDE suggests valid values
jurisdiction="JM",
fuzzy=True
)
# Access with confidence
if result["success"]:
description: str = result["data"]["description"]
found: bool = result["data"]["found"]
```
Advanced configuration [#advanced-configuration]
Custom timeout [#custom-timeout]
```python
client = VerityClient(
api_key="vrt_live_YOUR_API_KEY",
timeout=60 # seconds
)
```
Automatic retries [#automatic-retries]
The SDK retries transient failures (rate limits, timeouts) with exponential backoff. Max 3 retries by default. This is automatic—you don't need to configure it.
What the SDK doesn't do [#what-the-sdk-doesnt-do]
The SDK wraps the REST API. It doesn't:
* Cache responses (build your own cache if needed)
* Batch requests (send them concurrently if you need parallelism)
* Make coverage decisions (it returns what's in the policies, you interpret them)
These are intentional design choices. The SDK is low-level and unopinionated.
Resources [#resources]
* **PyPI**: [verity-python](https://pypi.org/project/verity-python/)
* **GitHub**: [backworkai/verity-python](https://github.com/backworkai/verity-python)
* **API Reference**: [All Endpoints](/docs/api)
* **Issues**: [Report a bug](https://github.com/backworkai/verity-python/issues)
Next steps [#next-steps]
# Ruby SDK
URL: /docs/sdks/ruby
Official Verity SDK for Ruby with resource-oriented API clients
The Verity Ruby SDK provides resource-oriented access to Medicare coverage intelligence, medical code lookup, policies, coverage criteria, prior authorization checks, spending data, and webhooks.
The Ruby SDK is not published to RubyGems yet. Install from source until the first package release is cut.
Installation [#installation]
```bash
git clone https://github.com/backworkai/verity-ruby.git
cd verity-ruby
bundle install
```
Requires Ruby 2.7+.
Quick Start [#quick-start]
```ruby
require 'verity'
client = Verity::Client.new(api_key: 'vrt_live_YOUR_API_KEY')
health = client.health
puts health.dig('data', 'status')
```
Get your API key from the [Developer Console](/console/keys).
Authentication [#authentication]
```ruby
client = Verity::Client.new(
api_key: ENV.fetch('VERITY_API_KEY'),
base_url: 'https://verity.backworkai.com/api/v1'
)
```
Common Use Cases [#common-use-cases]
Look Up a Medical Code [#look-up-a-medical-code]
```ruby
result = client.codes.lookup('76942', include: ['rvu', 'policies'])
data = result['data']
puts "#{data['code']}: #{data['description']}"
puts "Policies: #{data['policies']&.length || 0}"
```
Search Policies [#search-policies]
```ruby
result = client.policies.list(
q: 'ultrasound guidance',
mode: 'keyword',
policy_type: 'LCD',
jurisdiction: 'JM',
limit: 10
)
result['data'].each do |policy|
puts "#{policy['policy_id']}: #{policy['title']}"
end
```
Check Prior Authorization [#check-prior-authorization]
```ruby
result = client.prior_auth.check(
procedure_codes: ['27447'],
diagnosis_codes: ['M17.11'],
state: 'TX',
payer: 'Medicare'
)
data = result['data']
puts "PA required: #{data['pa_required']}"
puts "Reason: #{data['reason']}"
```
Resources [#resources]
* **GitHub**: [backworkai/verity-ruby](https://github.com/backworkai/verity-ruby)
* **API Reference**: [All Endpoints](/docs/api)
* **Issues**: [Report a bug](https://github.com/backworkai/verity-ruby/issues)
# TypeScript SDK
URL: /docs/sdks/typescript
Official Verity SDK for TypeScript and Node.js with full type definitions
The official Verity TypeScript SDK provides a type-safe way to integrate Medicare coverage intelligence into your TypeScript, JavaScript, and Node.js applications.
Installation [#installation]
Install via npm, yarn, or pnpm:
```bash
npm install verity-api
# or
yarn add verity-api
# or
pnpm add verity-api
```
**Requirements**: Node.js 18+ or modern browser with fetch API
Quick Start [#quick-start]
```typescript
import { VerityClient } from 'verity-api';
// Initialize the client
const client = new VerityClient('vrt_live_YOUR_API_KEY');
// Make your first request
const health = await client.health();
console.log(health.data.status); // "healthy"
```
Authentication [#authentication]
Set your API key when initializing the client:
```typescript
import { VerityClient } from 'verity-api';
// Option 1: Pass directly
const client = new VerityClient('vrt_live_YOUR_API_KEY');
// Option 2: With configuration object
const client = new VerityClient({
apiKey: 'vrt_live_YOUR_API_KEY',
baseUrl: 'https://verity.backworkai.com/api/v1', // optional
timeout: 30000 // optional, in milliseconds
});
// Option 3: From environment variable
const client = new VerityClient(process.env.VERITY_API_KEY!);
```
Get your API key from the [Developer Console](/console/keys).
Common Use Cases [#common-use-cases]
Check if a Procedure Needs Prior Authorization [#check-if-a-procedure-needs-prior-authorization]
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Check for a knee replacement in Texas
const result = await client.checkPriorAuth({
procedureCodes: ['27447'], // Total knee replacement
diagnosisCodes: ['M17.11'], // Unilateral primary osteoarthritis, right knee
state: 'TX'
});
if (result.data.pa_required) {
console.log('Warning: Prior authorization required!');
console.log(`Confidence: ${result.data.confidence}`);
console.log(`Reason: ${result.data.reason}`);
// Show what documentation is needed
console.log('\nDocumentation checklist:');
result.data.documentation_checklist?.forEach(item => {
console.log(` • ${item}`);
});
// Show matched policies
console.log(`\nMatched ${result.data.matched_policies?.length} policies:`);
result.data.matched_policies?.slice(0, 3).forEach(policy => {
console.log(` • ${policy.policy_id}: ${policy.title}`);
});
} else {
console.log('No prior authorization needed');
}
```
Look Up Procedure Code with Coverage Info [#look-up-procedure-code-with-coverage-info]
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Look up a code with RVU data and policies
const result = await client.lookupCode({
code: '76942', // Ultrasound guidance
include: ['rvu', 'policies']
});
const codeData = result.data;
console.log(`Code: ${codeData.code}`);
console.log(`Description: ${codeData.description}`);
// Show reimbursement info
if (codeData.rvu) {
console.log('\nReimbursement (2026):');
console.log(` Work RVU: ${codeData.rvu.work_rvu}`);
console.log(` Facility price: $${codeData.rvu.facility_price}`);
console.log(` Non-facility price: $${codeData.rvu.non_facility_price}`);
}
// Show coverage policies
if (codeData.policies) {
console.log(`\nFound ${codeData.policies.length} coverage policies:`);
codeData.policies.slice(0, 5).forEach(policy => {
console.log(` • [${policy.disposition}] ${policy.title}`);
});
}
```
Search Coverage Policies by Keyword [#search-coverage-policies-by-keyword]
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Search for policies about diabetes CGM devices
const result = await client.listPolicies({
q: 'continuous glucose monitoring diabetes',
policyType: 'LCD', // Local Coverage Determinations
status: 'active',
limit: 10
});
console.log(`Found ${result.data.length} active LCDs about CGM:\n`);
result.data.forEach(policy => {
console.log(`Policy: ${policy.policy_id}`);
console.log(`Title: ${policy.title}`);
console.log(`Jurisdiction: ${policy.jurisdiction || 'National'}`);
console.log(`Effective: ${policy.effective_date || 'N/A'}`);
console.log('---');
});
```
Compare Coverage Across Jurisdictions [#compare-coverage-across-jurisdictions]
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Compare ultrasound guidance coverage across different MACs
const result = await client.comparePolicies({
procedureCodes: ['76942'],
jurisdictions: ['J05', 'J06', 'J12', 'JM'] // Different MAC jurisdictions
});
const comparison = result.data.comparison;
console.log('Coverage comparison across jurisdictions:\n');
comparison?.forEach(juris => {
console.log(`${juris.jurisdiction} (${juris.mac_name}):`);
console.log(` States: ${juris.states?.join(', ')}`);
console.log(` Policies: ${juris.policies?.length}`);
juris.policies?.forEach(policy => {
console.log(` • ${policy.policy_id}: ${policy.disposition}`);
});
console.log();
});
```
Monitor Policy Changes [#monitor-policy-changes]
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Get policies updated in the last 7 days
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
const result = await client.getPolicyChanges({
since: sevenDaysAgo.toISOString(),
changeType: 'updated',
limit: 20
});
console.log('Policy changes in the last 7 days:\n');
result.data.forEach(change => {
console.log(`Policy: ${change.policy_id}`);
console.log(`Change: ${change.change_type}`);
console.log(`Summary: ${change.change_summary || 'No summary'}`);
console.log(`Timestamp: ${change.timestamp}`);
console.log('---');
});
```
Get Detailed Policy Information [#get-detailed-policy-information]
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Get full policy details with criteria
const result = await client.getPolicy('L33831', {
include: ['criteria', 'codes', 'attachments']
});
const policy = result.data;
console.log(`Policy: ${policy.title}`);
console.log(`Type: ${policy.policy_type}`);
console.log(`Status: ${policy.status}`);
console.log(`Effective: ${policy.effective_date || 'N/A'}`);
// Show coverage criteria
if (policy.criteria) {
console.log('\nCoverage Criteria:');
Object.entries(policy.criteria).forEach(([section, blocks]) => {
console.log(`\n${section.toUpperCase()}:`);
blocks.slice(0, 3).forEach(block => { // Show first 3
console.log(` • ${block.text?.substring(0, 100)}...`);
});
});
}
// Show covered codes
if (policy.codes) {
console.log(`\nCovers ${policy.codes.length} codes`);
policy.codes.slice(0, 10).forEach(code => {
console.log(` • ${code.code} (${code.code_system}): ${code.disposition}`);
});
}
```
Search Coverage Criteria [#search-coverage-criteria]
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Search for specific coverage criteria about BMI requirements
const result = await client.searchCriteria({
q: 'BMI greater than 40',
section: 'indications',
policyType: 'LCD',
limit: 10
});
console.log('BMI-related coverage criteria:\n');
result.data.forEach(criteria => {
console.log(`Policy: ${criteria.policy_id}`);
console.log(`Section: ${criteria.section}`);
console.log(`Text: ${criteria.text?.substring(0, 200)}...`);
console.log(`Tags: ${criteria.tags?.join(', ')}`);
console.log('---');
});
```
List MAC Jurisdictions [#list-mac-jurisdictions]
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
const result = await client.listJurisdictions();
console.log('Medicare Administrative Contractors (MACs):\n');
result.data.forEach(jurisdiction => {
console.log(`${jurisdiction.jurisdiction_code}: ${jurisdiction.mac_name}`);
console.log(` States: ${jurisdiction.states?.join(', ')}`);
console.log(` Type: ${jurisdiction.mac_type || 'N/A'}`);
console.log();
});
```
Research Prior Auth with AI Web Search [#research-prior-auth-with-ai-web-search]
For commercial payers or when you need real-time payer website intelligence:
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Async mode (default) - returns research_id for polling
const research = await client.researchPriorAuth({
procedureCodes: ['27447'],
payer: 'UnitedHealthcare',
state: 'TX'
});
const researchId = research.data.research_id;
console.log(`Research started: ${researchId}`);
// Poll for results
let status;
do {
await new Promise(resolve => setTimeout(resolve, 2000));
status = await client.getPriorAuthResearch(researchId);
} while (!['completed', 'failed'].includes(status.data.status));
if (status.data.status === 'completed') {
console.log('Determination:', status.data.result?.determination);
console.log('Sources:', status.data.result?.sources);
}
// Or use sync mode to wait for completion
const syncResult = await client.researchPriorAuth({
procedureCodes: ['27447'],
payer: 'Aetna',
state: 'CA',
sync: true
});
console.log(syncResult.data.result?.determination);
```
Get Medicaid Spending Data [#get-medicaid-spending-data]
```typescript
import { VerityClient } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Single code
const result = await client.getSpendingByCode({ code: 'T1019' });
const spending = result.data['T1019'];
console.log(`Total paid: $${spending.total_paid}`);
console.log(`Total claims: ${spending.total_claims}`);
spending.by_year.forEach(year => {
console.log(` ${year.year}: $${year.total_paid} (${year.total_claims} claims)`);
});
// Multiple codes with year filter
const multi = await client.getSpendingByCode({
codes: ['T1019', 'T1020'],
year: 2023
});
```
Browser Usage [#browser-usage]
The SDK works in modern browsers using native fetch:
```html
Loading...
```
Error Handling [#error-handling]
The SDK provides structured exceptions for different error types:
```typescript
import {
VerityClient,
VerityError,
AuthenticationError,
ValidationError,
NotFoundError,
RateLimitError
} from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
try {
const result = await client.lookupCode({ code: 'INVALID' });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key:', error.message);
} else if (error instanceof ValidationError) {
console.error('Invalid parameters:', error.message);
if (error.details) {
console.error('Details:', error.details);
}
} else if (error instanceof NotFoundError) {
console.error('Resource not found:', error.message);
} else if (error instanceof RateLimitError) {
console.error(`Rate limit exceeded. Resets at: ${error.reset}`);
console.error(`Limit: ${error.limit}, Remaining: ${error.remaining}`);
} else if (error instanceof VerityError) {
console.error(`API error: ${error.message} (code: ${error.code})`);
if (error.hint) {
console.error(`Hint: ${error.hint}`);
}
}
}
```
Response Format [#response-format]
All methods return typed responses:
```typescript
interface ApiResponse {
success: true;
data: T;
meta?: {
request_id?: string;
timestamp?: string;
[key: string]: any;
};
}
// Or error response
interface ErrorResponse {
success: false;
error: {
code: string;
message: string;
hint?: string;
details?: Record;
};
meta?: {
request_id?: string;
timestamp?: string;
};
}
```
TypeScript Integration [#typescript-integration]
The SDK includes complete type definitions:
```typescript
import { VerityClient, CodeLookupData, PriorAuthResult } from 'verity-api';
const client = new VerityClient(process.env.VERITY_API_KEY!);
// Full type safety with autocomplete
const codeResult = await client.lookupCode({
code: '76942',
include: ['rvu', 'policies'],
jurisdiction: 'JM',
fuzzy: true
});
// TypeScript knows the exact shape of the response
if (codeResult.success) {
const data: CodeLookupData = codeResult.data;
const description: string | null = data.description;
const found: boolean = data.found;
const rvu = data.rvu; // Type: RvuData | undefined
console.log(`${description} - $${rvu?.facility_price}`);
}
```
Express.js Integration [#expressjs-integration]
Example Express.js endpoint using the SDK:
```typescript
import express from 'express';
import { VerityClient, VerityError } from 'verity-api';
const app = express();
const verity = new VerityClient(process.env.VERITY_API_KEY!);
app.get('/api/check-code/:code', async (req, res) => {
try {
const result = await verity.lookupCode({
code: req.params.code,
include: ['rvu', 'policies']
});
res.json(result);
} catch (error) {
if (error instanceof VerityError) {
res.status(error.statusCode || 500).json({
error: error.message,
code: error.code
});
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
});
app.listen(3000);
```
Resources [#resources]
* **npm**: [verity-api](https://www.npmjs.com/package/verity-api)
* **GitHub**: [backworkai/verity-ts](https://github.com/backworkai/verity-ts)
* **API Reference**: [All Endpoints](/docs/api)
* **Issues**: [Report a bug](https://github.com/backworkai/verity-ts/issues)
Next Steps [#next-steps]