Pyrls API Reference
Access evidence-based drug counseling points and pharmacotherapy resources through a simple REST API. Build pharmacy tools, clinical decision support, and patient education applications.
https://api.pyrls.com/v3/Authentication
All API requests require a Bearer token in the Authorization header. You can obtain your API key from the Pyrls Developer Dashboard.
Authorization: Bearer YOUR_API_KEYCounseling Points
Retrieve evidence-based patient counseling information for medications. The API supports two access patterns: a flexible search endpoint with fuzzy matching, and a precise NDC lookup for exact identification by National Drug Code.
Search
Performs fuzzy, exact, or fallback matching against the counseling database.
/counselingParameters
| Parameter | Required | Default | Description |
|---|---|---|---|
q | Required | — | Search query string |
limit | Optional | 5 | Results per page (min: 1, max: 20) |
mode | Optional | fuzzy | Search mode: fuzzy, exact, or fallback |
Search Modes
Typo-tolerant fuzzy matching with favor for start-of-field similarity.
Only returns exact field-value matches.
Uses every effort to return at least one most relevant result.
curl --location 'https://api.pyrls.com/v3/counseling?q=metoprolol&limit=5&mode=fuzzy' \
--header 'Authorization: Bearer YOUR_API_KEY'NDC Lookup
Performs an exact-match lookup by National Drug Code (NDC).
/counseling/ndc/:ndcNDC Input Normalization
Both /counseling/ndc/:ndc and /counseling?q=... normalize numeric inputs:
| Input | Behavior | Example |
|---|---|---|
| Pure digits, >9 chars | Trimmed to first 9 digits | 003784105123 → 003784105 |
| Pure digits, ≤9 chars | Unchanged | 003784105 → 003784105 |
| Non-numeric | Unchanged | metformin → metformin |
NDC Response
Found (200):
{
"data": {
"id": "1",
"genericName": "abacavir",
"brandNames": ["Ziagen"],
"counseling": [...]
}
}Not Found (200):
{
"data": null
}curl --location 'https://api.pyrls.com/v3/counseling/ndc/003784105' \
--header 'Authorization: Bearer YOUR_API_KEY'Search Response Format
Response Body (200)
| Field | Type | Description |
|---|---|---|
total | integer | Total number of matching query results. |
hasMore | boolean | Whether additional results are available beyond the limit. |
results | array | Array of scored result objects. |
results[i].score | integer | Relevance score of the item against the query. |
results[i].item | object | The matched item data (fields below). |
item.routes | string[] | Routes/variants of administration (e.g., oral) applicable to the context of counseling points provided. |
item.genericName | string | Generic name of the drug. |
item.brandNames | string[] | The applicable brand names in the context of the counseling points for the drug. |
item.dosageForms | string[] | Common dosage forms applicable to the context of counseling points provided. |
item.counseling | object[] | Counseling points grouped by section. |
Counseling Field
The counseling field contains an array of objects, each representing a dedicated group of points under a shared section (e.g., Proper Use, Side Effects, Warnings).
| Field | Type | Description |
|---|---|---|
section | string | Section name (e.g., "Proper Use", "Side Effects", "Warnings"). |
data | object[] | Array of counseling point objects. |
data[i].text | string | The counseling point text (HTML formatted). |
data[i].moreInfo | string | Expanded detail or clinical context (HTML formatted). |
"counseling": [
{
"section": "Proper Use",
"data": [
{
"text": "<p>Take at the <strong>same time each day</strong>, with or without food</p>",
"moreInfo": "<p>Food does not alter the bioavailability of lisinopril tablets or solution.</p>"
}
]
},
{
"section": "Side Effects",
"data": [
{
"text": "<p><strong>Symptomatic</strong> hypotension (e.g. light-headedness) after starting therapy</p>",
"moreInfo": "<p>Patients should be cautious in the <strong>first few days</strong> of therapy...</p>"
}
]
},
{
"section": "Warnings",
"data": [
{
"text": "Avoid use of over-the-counter <strong>NSAIDs</strong> (e.g. ibuprofen, naproxen)",
"moreInfo": "<p>Use of <strong>NSAIDs</strong> with ACE inhibitors may result in increased risk...</p>"
}
]
}
]Pharmacotherapy Resources
Access curated pharmacotherapy resources including clinical reference charts, comparison tables, and dosing guides. Search by resource names, medication class terms, or individual drug names — the keyword set includes related medication names (e.g., searching semaglutide, tirzepatide, or liraglutide will return relevant GLP-1 resources).
/resourcesParameters
| Parameter | Required | Default | Description |
|---|---|---|---|
q | Optional | — | Search query — matches against resource titles and keywords, including related medication names. |
filters | Optional | — | Comma-separated list of resource kinds. Corresponds to kind on the response object. Currently available: chart |
Search Behavior
By drug name: Search for individual medication names like semaglutide, tirzepatide, or liraglutide to find resources containing those drugs.
By class or topic: Search using medication class terms like glp1, sglt2, or diabetes to find related resources.
Multi-result queries: Broader queries like diabetes may return multiple chart options, including multi-page PDFs such as "Type 2 Diabetes Pharmacotherapy."
curl --location 'https://api.pyrls.com/v3/resources?q=glp1' \
--header 'Authorization: Bearer YOUR_API_KEY'Response Format
Response Body (200)
| Field | Type | Description |
|---|---|---|
total | integer | Total number of items returned. |
hasMore | boolean | Whether additional items are available. |
results | array | List of scored resource items. |
results[i].score | number | Relevance score. |
results[i].item | object | The resource item (schema below). |
Resource Item Schema
| Field | Type | Description |
|---|---|---|
id | string | Unique resource identifier. |
kind | string | Resource type (e.g., "chart"). |
labels | string[] | Classification labels (e.g., "pharmacotherapy", "product_comparison", "dosing_guidance"). |
keywords | string[] | Searchable keywords including drug class terms and individual medication names (e.g., "glp1", "semaglutide", "tirzepatide"). |
properties | object | Resource content details (below). |
Properties Object
| Field | Type | Description |
|---|---|---|
name | string | Display name of the resource. |
version | string | Resource version (e.g., "2025.11.16.1.0.0"). |
pdf_url | string | URL to the full PDF version of the resource. |
images | Image[] | Array of image assets for the resource (see below). |
Image Object
| Field | Type | Description |
|---|---|---|
id | string | Unique image identifier. |
title | string | Image title or caption. |
description | string | Description of the image content. |
image_url | string | Direct URL to the image asset. |
width | number | Image width in pixels. |
height | number | Image height in pixels. |
TypeScript Interfaces
interface Image {
id: string;
title: string;
description: string;
image_url: string;
width: number;
height: number;
}
interface ResourceProperties {
name: string;
version: string;
pdf_url: string;
images: Image[];
}
interface PharmacotherapyResource {
id: string;
kind: string;
labels: string[];
keywords: string[];
properties: ResourceProperties;
}
interface ScoredItem<T> {
score: number;
item: T;
}
interface ResourcesResponse {
total: number;
hasMore: boolean;
results: ScoredItem<PharmacotherapyResource>[];
}Example Response
Response for GET /resources?q=diabetes — returns multiple resources including multi-page charts:
{
"total": 2,
"hasMore": false,
"results": [
{
"score": 3,
"item": {
"id": "4",
"kind": "chart",
"labels": [
"pharmacotherapy",
"product_comparison",
"dosing_guidance",
"injectables",
"endocrinology"
],
"keywords": [
"glp1",
"gip_glp1",
"receptor_agonist",
"semaglutide",
"tirzepatide",
"liraglutide",
"dulaglutide",
"exenatide",
"diabetes",
"type_2_diabetes",
"weight_management",
"obesity"
],
"properties": {
"name": "GLP-1 and GIP/GLP-1 Receptor Agonist Chart",
"version": "2025.11.16.1.0.0",
"pdf_url": "https://firebasestorage.googleapis.com/...",
"images": [
{
"id": "1",
"title": "GLP-1 and GIP/GLP-1 Receptor Agonists Comparison",
"description": "A chart comparing GLP-1 and dual GIP/GLP-1 receptor agonist medications",
"image_url": "https://firebasestorage.googleapis.com/...",
"width": 1500,
"height": 1940
}
]
}
}
},
{
"score": 1,
"item": {
"id": "8",
"kind": "chart",
"labels": [
"pharmacotherapy",
"product_comparison",
"dosing_guidance",
"endocrinology",
"diabetes"
],
"keywords": [
"diabetes",
"type_2_diabetes",
"t2dm",
"pharmacotherapy",
"metformin",
"sglt2",
"dpp4",
"sulfonylurea",
"thiazolidinedione",
"glp1",
"insulin",
"a1c",
"glycemic_control",
"oral_antidiabetic"
],
"properties": {
"name": "Diabetes Pharmacotherapy Review",
"version": "2026.01.01.1.0.0",
"pdf_url": "https://firebasestorage.googleapis.com/...",
"images": [
{
"id": "1",
"title": "T2DM Pharmacotherapy Overview",
"description": "Type 2 diabetes pharmacotherapy review including drug classes, mechanisms, efficacy, and place in therapy",
"image_url": "https://cosmas-api.vercel.app/dm1.png",
"width": 1500,
"height": 1940
},
{
"id": "2",
"title": "T2DM Pharmacotherapy Continued",
"description": "Type 2 diabetes pharmacotherapy review continued",
"image_url": "https://cosmas-api.vercel.app/dm2.png",
"width": 1500,
"height": 1940
}
]
}
}
}
]
}Error Handling
All errors return a consistent JSON structure. Use the code field for programmatic handling and message for user-facing display.
{
"error": {
"code": "validation_error",
"status": 400,
"message": "Request validation failed",
"request_id": "req_abc123",
"errors": [
{
"param": "limit",
"code": "out_of_range",
"message": "limit must be between 1 and 100"
}
],
"help_url": "",
"retryable": false,
"retry_after": null
}
}Error Object Fields
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code for programmatic handling. |
status | integer | HTTP status code (mirrored in body for convenience). |
message | string | Human-readable summary. Safe to display in UI. |
request_id | string | Unique request identifier. Include when contacting support. |
errors | array | Field-level errors (validation failures only). |
errors[].param | string | null | Field path using dot notation, or null for cross-field errors. |
errors[].code | string | Machine-readable code for this field error. |
errors[].message | string | Human-readable description of the field error. |
help_url | string | Link to documentation for this error (when available). |
retryable | boolean | Whether retrying the same request might succeed. |
retry_after | integer | null | Seconds to wait before retrying (for rate limits). |
HTTP Status Codes
| Status | Meaning |
|---|---|
200 | Success |
400 | Bad Request — Invalid parameters or validation failed |
401 | Unauthorized — Missing or invalid API key |
403 | Forbidden — Valid API key but insufficient permissions |
404 | Not Found — Resource doesn't exist |
409 | Conflict — Resource already exists or state conflict |
429 | Too Many Requests — Rate limit exceeded |
500 | Internal Server Error — Something went wrong on our end |
Error Codes Reference
Validation Errors (400)
| Code | Description |
|---|---|
validation_error | One or more fields failed validation. Check errors array. |
invalid_format | Field value is malformed (wrong type, bad format). |
required_field | Required field is missing. |
out_of_range | Value is outside acceptable bounds. |
cross_field | Multiple fields conflict. |
Authentication Errors (401)
| Code | Description |
|---|---|
unauthorized | No API key provided. |
invalid_api_key | API key is malformed or doesn't exist. |
expired_token | API key or token has expired. |
Other Error Codes
| Code | Status | Description |
|---|---|---|
forbidden | 403 | Valid credentials but not allowed to perform this action. |
not_found | 404 | Generic not found. |
resource_not_found | 404 | Specific resource doesn't exist. |
conflict | 409 | Generic conflict. |
already_exists | 409 | Attempted to create a resource that already exists. |
rate_limited | 429 | Too many requests. Check retry_after for when to retry. |
internal_error | 500 | Unexpected error. We've been notified. |
service_unavailable | 500 | Temporarily unavailable. Retry with exponential backoff. |
Handling Errors in Code
const response = await fetch('https://api.pyrls.com/v3/counseling?q=metoprolol', {
headers: { Authorization: 'Bearer YOUR_API_KEY' }
});
const data = await response.json();
if (data.error) {
switch (data.error.code) {
case 'rate_limited':
// Wait and retry
await sleep(data.error.retry_after * 1000);
return retry();
case 'validation_error':
// Show field-level errors to user
data.error.errors.forEach(err => {
showFieldError(err.param, err.message);
});
break;
case 'unauthorized':
case 'invalid_api_key':
// Redirect to authentication
redirectToLogin();
break;
default:
// Log and show generic message
console.error(`API Error [${data.error.request_id}]:`, data.error);
showToast('Something went wrong. Please try again.');
}
}request_id when contacting support — it helps us find exactly what happened.