Developer Platform

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.

Base URL
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 Header
Authorization: Bearer YOUR_API_KEY
💡
Keep your API key secret. Do not expose it in client-side code or public repositories.

Counseling 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.

Performs fuzzy, exact, or fallback matching against the counseling database.

GET/counseling

Parameters

ParameterRequiredDefaultDescription
qRequiredSearch query string
limitOptional5Results per page (min: 1, max: 20)
modeOptionalfuzzySearch mode: fuzzy, exact, or fallback

Search Modes

fuzzy

Typo-tolerant fuzzy matching with favor for start-of-field similarity.

exact

Only returns exact field-value matches.

fallback

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).

GET/counseling/ndc/:ndc

NDC Input Normalization

Both /counseling/ndc/:ndc and /counseling?q=... normalize numeric inputs:

InputBehaviorExample
Pure digits, >9 charsTrimmed to first 9 digits003784105123003784105
Pure digits, ≤9 charsUnchanged003784105003784105
Non-numericUnchangedmetforminmetformin

NDC Response

Found (200):

json
{
  "data": {
    "id": "1",
    "genericName": "abacavir",
    "brandNames": ["Ziagen"],
    "counseling": [...]
  }
}

Not Found (200):

json
{
  "data": null
}
curl --location 'https://api.pyrls.com/v3/counseling/ndc/003784105' \
--header 'Authorization: Bearer YOUR_API_KEY'

Search Response Format

Response Body (200)

FieldTypeDescription
totalintegerTotal number of matching query results.
hasMorebooleanWhether additional results are available beyond the limit.
resultsarrayArray of scored result objects.
results[i].scoreintegerRelevance score of the item against the query.
results[i].itemobjectThe matched item data (fields below).
item.routesstring[]Routes/variants of administration (e.g., oral) applicable to the context of counseling points provided.
item.genericNamestringGeneric name of the drug.
item.brandNamesstring[]The applicable brand names in the context of the counseling points for the drug.
item.dosageFormsstring[]Common dosage forms applicable to the context of counseling points provided.
item.counselingobject[]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).

FieldTypeDescription
sectionstringSection name (e.g., "Proper Use", "Side Effects", "Warnings").
dataobject[]Array of counseling point objects.
data[i].textstringThe counseling point text (HTML formatted).
data[i].moreInfostringExpanded detail or clinical context (HTML formatted).
Example counseling array
"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).

GET/resources
💡
When no parameters are provided, the endpoint returns the latest version of all available resources.

Parameters

ParameterRequiredDefaultDescription
qOptionalSearch query — matches against resource titles and keywords, including related medication names.
filtersOptionalComma-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)

FieldTypeDescription
totalintegerTotal number of items returned.
hasMorebooleanWhether additional items are available.
resultsarrayList of scored resource items.
results[i].scorenumberRelevance score.
results[i].itemobjectThe resource item (schema below).

Resource Item Schema

FieldTypeDescription
idstringUnique resource identifier.
kindstringResource type (e.g., "chart").
labelsstring[]Classification labels (e.g., "pharmacotherapy", "product_comparison", "dosing_guidance").
keywordsstring[]Searchable keywords including drug class terms and individual medication names (e.g., "glp1", "semaglutide", "tirzepatide").
propertiesobjectResource content details (below).

Properties Object

FieldTypeDescription
namestringDisplay name of the resource.
versionstringResource version (e.g., "2025.11.16.1.0.0").
pdf_urlstringURL to the full PDF version of the resource.
imagesImage[]Array of image assets for the resource (see below).

Image Object

FieldTypeDescription
idstringUnique image identifier.
titlestringImage title or caption.
descriptionstringDescription of the image content.
image_urlstringDirect URL to the image asset.
widthnumberImage width in pixels.
heightnumberImage height in pixels.

TypeScript Interfaces

typescript
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:

json
{
  "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 response structure
{
  "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

FieldTypeDescription
codestringMachine-readable error code for programmatic handling.
statusintegerHTTP status code (mirrored in body for convenience).
messagestringHuman-readable summary. Safe to display in UI.
request_idstringUnique request identifier. Include when contacting support.
errorsarrayField-level errors (validation failures only).
errors[].paramstring | nullField path using dot notation, or null for cross-field errors.
errors[].codestringMachine-readable code for this field error.
errors[].messagestringHuman-readable description of the field error.
help_urlstringLink to documentation for this error (when available).
retryablebooleanWhether retrying the same request might succeed.
retry_afterinteger | nullSeconds to wait before retrying (for rate limits).

HTTP Status Codes

StatusMeaning
200Success
400Bad Request — Invalid parameters or validation failed
401Unauthorized — Missing or invalid API key
403Forbidden — Valid API key but insufficient permissions
404Not Found — Resource doesn't exist
409Conflict — Resource already exists or state conflict
429Too Many Requests — Rate limit exceeded
500Internal Server Error — Something went wrong on our end

Error Codes Reference

Validation Errors (400)

CodeDescription
validation_errorOne or more fields failed validation. Check errors array.
invalid_formatField value is malformed (wrong type, bad format).
required_fieldRequired field is missing.
out_of_rangeValue is outside acceptable bounds.
cross_fieldMultiple fields conflict.

Authentication Errors (401)

CodeDescription
unauthorizedNo API key provided.
invalid_api_keyAPI key is malformed or doesn't exist.
expired_tokenAPI key or token has expired.

Other Error Codes

CodeStatusDescription
forbidden403Valid credentials but not allowed to perform this action.
not_found404Generic not found.
resource_not_found404Specific resource doesn't exist.
conflict409Generic conflict.
already_exists409Attempted to create a resource that already exists.
rate_limited429Too many requests. Check retry_after for when to retry.
internal_error500Unexpected error. We've been notified.
service_unavailable500Temporarily unavailable. Retry with exponential backoff.

Handling Errors in Code

typescript
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.');
  }
}
💡
Always include request_id when contacting support — it helps us find exactly what happened.