CPS API
Standards-based endpoints for instant credential verification, partner integrations, and streamlined recertification evidence — built with security, auditability, and employer trust.
What the CPS API is for
A pragmatic API that reduces support, improves employer confidence, and unlocks integrations — while looking enterprise‑grade from day one.
Instant Credential Verification
Public, read‑only confirmation of a credential’s status with holder initials and last4 — no PDFs or screenshots required.
Verifiable Digital Badges
Host Open Badges / JSON‑LD assertions so credentials render reliably on LinkedIn and HR platforms.
Eligibility & Scheduling
Read‑only partner checks for eligibility status and available exam windows (UTC time with friendly “ET” label).
Recert Evidence Intake
Trusted providers can submit signed activity claims (presenter/reviewer/preceptor, employer in‑service, etc.) for candidate review.
Receipts & Letters
Self‑service retrieval of receipts and verification letters to cut support requests.
Webhooks
Push events like credential.issued or window.opened to partner systems with HMAC signatures.
Quickstart
- Base URL:
https://api.pharmacystandards.org/v1
(example) - Auth: Public endpoints are rate‑limited. Partner endpoints require API key or OAuth client‑credentials.
- Time: All timestamps are ISO 8601 in UTC with a display label, e.g.,
display_tz: "ET"
. - Formats: JSON request/response; UTF‑8. Versioned via URL (
/v1
).
Public Endpoints
These endpoints avoid PII and are safe for employer lookups. Results include integrity headers for embedding.
Verify Credential
Confirm credential status using credential ID and a secondary check (initials+last4 or one‑time token).
# Request
GET /v1/credentials/verify?credential_id=CPOM-2025-000123&last4=4821
# 200 Response (example)
{
"credential_id": "CPOM-2025-000123",
"credential_name": "Certified Pharmacy Operations Manager (CPOM)",
"holder": { "initials": "JD", "last4": "4821" },
"status": "active",
"issued_at": "2025-06-10T14:05:00Z",
"expires_at": "2027-06-09T23:59:59Z",
"verify_url": "https://pharmacystandards.org/verify/CPOM-2025-000123",
"badge": {
"png_url": "https://pharmacystandards.org/badges/cpom-000123.png",
"assertion_url": "https://pharmacystandards.org/badges/abc123.json"
}
}
# Header: X-CPS-Signature: hmac-sha256 of body using your public key id
Open Badge Assertion
GET /v1/badges/{assertionId}.json
{
"@context": "https://w3id.org/openbadges/v3",
"type": ["Assertion"],
"id": "https://pharmacystandards.org/badges/abc123.json",
"recipient": { "type": "email", "hashed": true, "salt": "...", "identity": "sha256$..." },
"badge": "https://pharmacystandards.org/badges/cpom.json",
"verification": { "type": "HostedBadge" },
"issuedOn": "2025-06-10T14:05:00Z",
"expires": "2027-06-09T23:59:59Z"
}
Partner Endpoints
Require API key (header) or OAuth 2.0 client‑credentials. Keys are scoped and revocable.
Eligibility Check
GET /v1/eligibility?candidate_ext_id=EXT-90210&cert_id=CPOM
Authorization: Bearer <token>
{
"candidate_ext_id": "EXT-90210",
"cert_id": "CPOM",
"eligible": true,
"window": {
"start": "2025-09-01T00:00:00Z",
"end": "2025-09-30T23:59:59Z",
"display_tz": "ET"
},
"notes": "Eligible pending ID verification."
}
Submit Recertification Evidence
POST /v1/recert/evidence
Authorization: Bearer <token>
Content-Type: application/json
{
"candidate_ext_id": "EXT-90210",
"cert_id": "CPOM",
"activity_type": "presenter",
"hours": 10,
"start_date": "2025-04-18",
"end_date": "2025-04-18",
"provider_id": "ACME-CONF-2025",
"proof_url": "https://example.org/proofs/123",
"signature": "hmac-sha256(...payload...)"
}
# 202 Accepted
{ "evidence_id": "EV-7f2b", "status": "received" }
Webhooks
Receive real‑time events: credential.issued
, credential.revoked
, window.opened
, window.closed
, recert.submitted
, payment.received
, exam.scheduled
.
POST https://partner.example.com/hooks/cps
Headers:
X-CPS-Event: credential.issued
X-CPS-Signature: sha256=ab12cd...
Body:
{
"event": "credential.issued",
"id": "evt_47a",
"created": "2025-06-10T14:05:05Z",
"data": {
"credential_id": "CPOM-2025-000123",
"user_id": 91234
}
}
<?php
$secret = 'your_webhook_signing_secret';
$payload = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_CPS_SIGNATURE'] ?? '';
list($algo, $hash) = explode('=', $sig, 2);
$calc = hash_hmac('sha256', $payload, $secret);
if (!hash_equals($calc, $hash)) {
http_response_code(400);
exit('Invalid signature');
}
http_response_code(200);
echo 'ok';
Authentication & Security
API Keys / OAuth
Provision per‑partner keys or OAuth client‑credentials; rotate and revoke in the CPS Developer Portal.
Data Minimization
Public endpoints expose initials+last4 only. No addresses, DOB, or full emails. Audit logs on all partner actions.
Time & Locale
Return UTC timestamps; include display_tz
labels (e.g., "ET"). Avoid browser locale ambiguity.
Rate Limits & Errors
Type | Limit | Headers |
---|---|---|
Public verify | 60 req / minute / IP | X-RateLimit-Limit , X-RateLimit-Remaining |
Partner | 600 req / minute / key | same as above |
Status | Meaning | Example |
---|---|---|
400 | Validation error | { "error": "invalid_parameters", "details": {"last4": "required"} } |
401 | Auth failed | { "error": "invalid_api_key" } |
403 | Scope denied | { "error": "insufficient_scope" } |
404 | Not found | { "error": "credential_not_found" } |
409 | Conflict | { "error": "duplicate_evidence" } |
429 | Rate limited | { "error": "rate_limited" } |
500 | Server error | { "error": "server_error", "id": "req_abc123" } |
Sandbox & Testing
- Use
https://api.sandbox.pharmacystandards.org/v1
with your sandbox key. - Test credentials are reset nightly; responses include
X-CPS-Environment
header. - Postman collection and OpenAPI (JSON) available below.
Build on CPS
Request access, explore the spec, and start verifying credentials in minutes.