Payna is backed by Y Combinator

Reference

Licenses

The company license portfolio: every state, every activity type. These are entity level licenses. For licenses held by people, see Individuals.

Endpoints

GET/licensesList all licenses

Paginated list of every license record held by your company, ordered by state code. Filter with the query parameters below.

ParameterTypeDescription
statestringComma separated two-letter state codes, for example CA,NY,TX.
statusstringComma separated status values, for example active,pending. See the status model on this page.
license_typestringPartial match on the license type, for example Money Transmission.
verifiedbooleanRestrict to licenses Payna has or has not verified with the regulator.
pageintegerPage number, starting at 1. Defaults to 1.
limitintegerResults per page. Defaults to 50, maximum 200.
GET/licenses/summaryGet license summary

Aggregate counts across the whole portfolio. Cheap enough to call on a dashboard load or a startup health check. Use renewing_30_days to drive blocking logic.

GET/licenses/{state}Get license for a state

The single most recently updated license for a state. State codes are case insensitive. A state can hold more than one license, so check meta.total: when it is greater than 1, call GET /licenses?state=XX to retrieve all of them.

ParameterTypeDescription
state *stringTwo-letter US state code in the path, for example CA.

Requires the licenses capability on your key. Full response schemas are in the interactive reference.

Filtering

curl -s "https://app.payna.com/api/v1/licenses?state=CA,NY&status=active" \
  -H "Authorization: Bearer $PAYNA_API_KEY"

Filters combine with AND. state and status both accept comma separated lists, so the call above means California or New York, and active. Results are ordered by state code ascending.

A license record

{
  "data": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "state_code": "CA",
      "license_type": "California - DFPI Debt Collection License",
      "activity_type": "debt_collection",
      "license_number": "11622-99",
      "nmls_id": "2671499",
      "regulator": "DFPI",
      "status": "active",
      "sub_status": null,
      "raw_status": "Approved",
      "issued_date": "2025-07-17",
      "renewal_date": "2026-12-31",
      "days_until_renewal": 168,
      "verified": false,
      "status_detail": {
        "code": "licensed",
        "label": "Licensed",
        "category": "active",
        "intentional": false,
        "is_nmls": true,
        "portal": null,
        "source_text": "Approved"
      }
    }
  ],
  "meta": { "total": 37, "page": 1, "limit": 50, "synced_at": "2026-07-16T18:36:49Z" }
}

The status model

The top level status is a five value model aligned to NMLS raw status values.

StatusMeaning
activeLicensed and in good standing in that state.
deficientLicensed but with something outstanding against it, including expired licenses.
pendingFiled and waiting on the regulator.
applyingApplication in progress on our side, not yet with the regulator.
not_licensedNo license held. This is often deliberate, so check status_detail.intentional before treating it as a gap.

sub_status carries the detail underneath, for example withdrawn or expired.

// Correct: the derived category resolves the awkward cases.
const ok = license.status_detail.category === 'active'

// Wrong: raw_status is a verbatim regulator string. It differs
// between states and changes without notice.
const brittle = license.raw_status === 'Approved'

Fields on status_detail

FieldUse
codeStable machine slug, for example voluntary_withdrawal. Safe to branch on.
categoryCoarse bucket for display: active, in_progress, deficient, exited, not_pursued, needs_review.
intentionalTrue when being unlicensed is deliberate. This is the field that separates a real gap from a decision.
is_nmlsFalse for state portal jurisdictions that do not run through NMLS, such as Texas and Delaware debt collection.
portalThe state portal for non-NMLS jurisdictions, with a name and URL. Null for NMLS states.
labelHuman readable version of code. For display, not for logic.

Two things that surprise people

A state can hold more than one license

Different activity types, or a state level plus a city level entry. GET /licenses/{state} returns only the most recently updated one and puts the real count in meta.total. When that count is above 1, call GET /licenses?state=XX to get all of them. An integration that ignores this will silently read one license and miss the rest.

Not licensed is often correct

A not_licensed status, or no record at all, frequently means no license is required there, or the activity is covered by a surety bond instead. Check status_detail.intentional before surfacing it as a compliance problem.

Renewals

renewal_date is the deadline to file, and days_until_renewal counts down to it. A negative value means the date has passed with no renewal recorded. NMLS licenses run on a renewal cycle rather than a hard expiry, so a passed date is a signal to investigate rather than proof the license is dead.

For portfolio wide counts, GET /licenses/summary exposes renewing_soon at 90 days and renewing_30_days at 30, which is cheaper than paging the full list and computing it yourself.

See how Payna runs licensing.

Tell us a little about the company and we’ll walk through how Payna handles licensing and compliance in every US state.