Certifications
A certification is a credential an agent holds, such as a state insurance license, a carrier appointment or a product certification. Each certification has a type, can be tied to a provider company and a jurisdiction, and has an effective-dated status history.
Operations
| Operation | Scope | Description |
|---|---|---|
GET /certifications | read:agents | Certifications that have a current status. Inactive statuses such as Expired are included. |
GET /certifications/history | read:agents | All certification status periods, past and current. |
GET /certifications/{id} | read:agents | A single certification. |
POST /certifications | write:agents | Add or update a certification. See below. |
PATCH /certifications/{id} | write:agents | Change the flags, note or current status. |
POST /certifications/{id}/history | write:agents | Apply a status period to the history. |
DELETE /certifications/{id} | write:agents | Permanently delete a certification and its history. |
Filters
Both list operations accept agentCode, type, providerCompany, jurisdiction, status and identifier. GET /certifications/history also accepts from, through (YYYY-MM-DD) and modifiedSince (UTC timestamp), along with the standard paging and sorting parameters.
For example, to find an agent's status for a certification on a particular date:
GET /agency-management/acme/certifications/history?agentCode=A1051&type=LIFE&jurisdiction=US-TX&from=2026-03-15&through=2026-03-15
Response
{
"id": 812,
"agentCode": "A1051",
"type": "LIFE",
"jurisdiction": "US-TX",
"identifier": "TX-998877",
"isResidentCertification": true,
"isVerified": true,
"status": "Active",
"effectiveFrom": "2026-01-01",
"lastModified": "2026-09-24T15:02:11Z",
"lastModifiedBy": "jsmith@acme-agency.com"
}
providerCompany, note and effectiveThrough appear only when they have a value.
Statuses
| Status | Meaning |
|---|---|
Active | In good standing. |
Pending | Applied for or awaiting approval. |
Held | On hold. |
Suspended | Suspended (general). |
AdministrativeSuspension | Suspended for administrative reasons. |
RegulatorySuspension | Suspended by a regulator. |
Expired | Past its expiration date. |
Rejected | The application was rejected. |
Terminated | Terminated. |
Retired | Retired. |
Adding or updating a certification
POST /certifications is an add-or-update (upsert) operation. You don't need to know whether a certification already exists or what its id is. Send what you know, and AgencyMax either creates a new certification or updates the matching one.
This makes the operation well suited to syncing from license feeds such as NIPR, carrier appointment files or your own compliance system. It's also safe to retry.
POST /agency-management/acme/certifications
Content-Type: application/json
{
"agentCode": "A1051",
"type": "LIFE",
"jurisdiction": "US-TX",
"identifier": "TX-998877",
"isResidentCertification": true,
"isVerified": true,
"status": "Active",
"effectiveFrom": "2026-01-01",
"effectiveThrough": "2027-12-31",
"note": "Renewed via NIPR",
"initiator": "license-sync"
}
Request fields
| Field | Required | Notes |
|---|---|---|
agentCode | Yes | The agent must exist, otherwise 404. |
type | Yes | A configured certification type code. |
providerCompany | No | A provider company code, for carrier-specific appointments. |
jurisdiction | No | A jurisdiction code such as US-TX. |
identifier | No | The license or appointment number. |
isResidentCertification | Yes | true for a resident license, false for a non-resident one. |
isVerified | Yes | Whether the certification has been verified against an authoritative source. |
status | No | Defaults to Active. |
effectiveFrom | No | The start of the status period. Defaults to today. |
effectiveThrough | No | The end of the status period (inclusive). Leave it out for an open-ended period. |
note | No | A free-text note. |
initiator | Yes | See Auditing. |
How matching works
AgencyMax looks for an existing certification for the agent that matches all of the following:
| Field | Matching rule |
|---|---|
agentCode | Exact match. |
type | Exact match. |
providerCompany | Exact match. A missing provider company matches only certifications that have no provider company. |
jurisdiction | Exact match. A missing jurisdiction matches only certifications that have no jurisdiction. |
identifier | Exact match. A missing or blank identifier matches only certifications with no identifier (null or empty). |
The identifier is part of the match
Because identifier is one of the matching keys, sending a different license number for the same agent, type and jurisdiction creates a new certification rather than updating the existing one. The same happens if you include an identifier on one call and leave it out on the next. Send the fields the same way every time so your updates land on the certification you expect.
status, the effective dates, isVerified, isResidentCertification and note play no part in matching.
When there's no match: create
A new certification is created with the given details, and its status history starts with a single period (status from effectiveFrom through effectiveThrough).
- Response:
201 Created, with the certification andisNew: true.
When there's a match: update
The matching certification is updated:
isVerified,isResidentCertificationandnoteare overwritten with the values in the request.noteis replaced even if you leave it out, so an omitted note clears the existing one. To keep a note, send it again.- The status period (
status,effectiveFrom,effectiveThrough) is applied to the status history:- If the history already has a period with exactly this status and date range, nothing changes.
- Otherwise the period is merged into the history using the history rules below.
- Response:
200 OK, with the certification andisNew: false.
Default effective date on updates
If you leave out effectiveFrom, it defaults to today. When you resend an unchanged certification during a sync without effectiveFrom, AgencyMax may split the existing status period at today's date, even though the status hasn't changed. Always send the real effective dates from your source system.
Validation errors
| Condition | Response |
|---|---|
| The agent doesn't exist | 404 Not Found |
Unknown type | 400: The specified certification type is not recognized. |
Unknown providerCompany, jurisdiction or status | 400, with a message on the offending field |
| Missing required fields | 400 |
How status history is applied
A certification's status history is a list of periods that never overlap. When a new period is applied, whether through POST /certifications, POST /certifications/{id}/history or a status change, the new period always wins and the existing periods are adjusted around it:
- Existing periods that fall entirely inside the new period are removed.
- An existing period that fully contains the new period is split into a part before it and a part after it.
- An existing period that overlaps the start of the new period is shortened so it ends the day before the new period starts.
- An existing period that overlaps the end of the new period is pushed back so it starts the day after the new period ends.
- The new period is added.
Periods are inclusive of both effectiveFrom and effectiveThrough. A missing effectiveThrough means open-ended. The certification's current status is the period that covers today.
Adjacent periods with the same status are not merged. You may see Active from 2024-01-01 to 2025-05-31 followed by Active from 2025-06-01 to 2026-06-30, for example.
The same rules apply to every effective-dated resource in the Agency Management API: pay status, W9, assigned uplines and assigned levels.
Example 1: a suspension inside an active period
Existing history:
| Status | From | Through |
|---|---|---|
| Active | 2024-01-01 | (open) |
Apply Suspended from 2026-03-01 through 2026-03-31. The active period fully contains it, so it's split:
| Status | From | Through |
|---|---|---|
| Active | 2024-01-01 | 2026-02-28 |
| Suspended | 2026-03-01 | 2026-03-31 |
| Active | 2026-04-01 | (open) |
Example 2: a license expires
Existing history:
| Status | From | Through |
|---|---|---|
| Active | 2024-01-01 | (open) |
Apply Expired from 2026-09-01 (open-ended). The active period overlaps the start, so it's shortened:
| Status | From | Through |
|---|---|---|
| Active | 2024-01-01 | 2026-08-31 |
| Expired | 2026-09-01 | (open) |
Example 3: overlapping both neighbours
Existing history:
| Status | From | Through |
|---|---|---|
| Active | 2024-01-01 | 2025-12-31 |
| Expired | 2026-01-01 | (open) |
Apply Active from 2025-06-01 through 2026-06-30, for example a late-recorded renewal. The first period is shortened and the second is pushed back:
| Status | From | Through |
|---|---|---|
| Active | 2024-01-01 | 2025-05-31 |
| Active | 2025-06-01 | 2026-06-30 |
| Expired | 2026-07-01 | (open) |
Example 4: replacing history
Existing history:
| Status | From | Through |
|---|---|---|
| Pending | 2026-01-01 | 2026-01-31 |
| Active | 2026-02-01 | (open) |
Apply Active from 2025-12-15 (open-ended). Both existing periods fall inside the new one, so both are removed:
| Status | From | Through |
|---|---|---|
| Active | 2025-12-15 | (open) |
Changing the current status (PATCH)
PATCH /certifications/{id} accepts isResidentCertification, isVerified, note, status and initiator, following the partial update rules.
When status changes, the new status takes effect today and is open-ended, and the current period ends. To record a change with other dates, use the history operation instead.
Editing history directly
POST /certifications/{id}/history applies one status period to a specific certification:
{
"status": "RegulatorySuspension",
"effectiveFrom": "2026-02-10",
"effectiveThrough": "2026-02-24",
"initiator": "compliance@acme-agency.com"
}
Changing past history can affect anything calculated from it, including commission eligibility, compliance reports and statuses already shared with carriers. Use this operation to correct records, not for routine updates.