Every request requires an API key in the Authorization header. Sign up at /signup to get your key instantly.
Key format: sk_live_ prefix for production keys.
curl -H "Authorization: Bearer sk_live_abc123..." \
"https://api.pullfirst.com/v1/licenses/search?q=Johnson"Keys are shown once at creation. Store them securely. If lost, revoke and generate a new one from your dashboard.
Limits are per API key, enforced with a sliding window.
| Tier | Requests/day | Requests/min | API Keys |
|---|---|---|---|
| Free | 100 | 10 | 1 |
| Starter ($9.99/mo) | 1,000 | 30 | 2 |
| Pro ($49.99/mo) | 10,000 | 120 | 5 |
Every response includes rate limit headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1711756800
X-Request-Id: a1b2c3d4e5f67890abcdef1234567890When rate limited, the API returns 429:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Daily request limit exceeded. Upgrade at https://pullfirst.com/pricing",
"retryAfter": 3600
},
}All responses are JSON.
{
"data": [...],
"page": 1,
"pageSize": 25,
"totalCount": 150,
"totalPages": 6
}{
"licenseNumber": "BC808194",
"name": "Goat Design Build L.L.C.",
"status": "Issued",
"city": "Elk River"
}{
"error": {
"code": "not_found",
"message": "No contractor found with license number BC999999"
},
}| Code | Status | Meaning |
|---|---|---|
invalid_request | 400 | Missing or invalid parameters |
unauthorized | 401 | Missing or invalid API key |
not_found | 404 | Resource doesn't exist |
rate_limit_exceeded | 429 | Rate limit hit |
internal_error | 500 | Server error (include X-Request-Id header in support tickets) |
The core entity. A contractor is identified by license number.
Search contractors by name, DBA, or license number.
| Name | Type | Required | Description |
|---|---|---|---|
| q | string | No | Name, DBA, or license number (min 3 chars) |
| city | string | No | Filter by city |
| licenseType | string | No | License type (e.g., Electrical, Plumbing, Residential Contractors) |
| status | string | No | License status (Issued, Expired, Revoked) |
| hasEnforcement | boolean | No | Only contractors with enforcement actions |
| entityType | string | No | Business or Personal |
| state | string | No | State code (e.g., MN) |
| page | integer | No | Page number (default: 1) |
| pageSize | integer | No | Results per page (default: 25, max: 100) |
curl -H "Authorization: Bearer sk_live_abc123" \
"https://api.pullfirst.com/v1/licenses/search?q=Johnson+Electric&city=Minneapolis"{
"data": [
{
"licenseNumber": "EA045231",
"name": "Johnson Electric Inc",
"dbaName": "Johnson Electrical Services",
"status": "Issued",
"city": "Minneapolis",
"state": "MN",
"licenseType": "Electrical",
"licenseSubtype": "Class A Electrical",
"expirationDate": "2027-03-31",
"hasEnforcementAction": false
}
],
"page": 1,
"pageSize": 25,
"totalCount": 3,
"totalPages": 1
}Retrieve a specific contractor by license number.
| Name | Type | Required | Description |
|---|---|---|---|
| licenseNumber | string | Yes | The license number (e.g., BC808194) |
curl -H "Authorization: Bearer sk_live_abc123" \
"https://api.pullfirst.com/v1/licenses/EA045231"OSHA workplace safety inspections linked to this contractor. Includes violations, penalties, and match confidence.
| Name | Type | Required | Description |
|---|---|---|---|
| licenseNumber | string | Yes | The license number |
curl -H "Authorization: Bearer sk_live_abc123" \
"https://api.pullfirst.com/v1/licenses/EA045231/osha"Building permits matched to this contractor.
| Name | Type | Required | Description |
|---|---|---|---|
| licenseNumber | string | Yes | The license number |
curl -H "Authorization: Bearer sk_live_abc123" \
"https://api.pullfirst.com/v1/licenses/EA045231/permits"Contractors sharing the same address or phone. Useful for detecting contractors who reopened under a new name after enforcement action.
| Name | Type | Required | Description |
|---|---|---|---|
| licenseNumber | string | Yes | The license number |
curl -H "Authorization: Bearer sk_live_abc123" \
"https://api.pullfirst.com/v1/licenses/EA045231/related"DLI disciplinary orders — fines, suspensions, revocations, consent orders.
Search enforcement actions with Gridify filtering.
| Name | Type | Required | Description |
|---|---|---|---|
| filter | string | No | Gridify filter expression |
| orderBy | string | No | Sort field (default: OrderDate desc) |
| page | integer | No | Page number (default: 1) |
| pageSize | integer | No | Results per page (default: 20, max: 100) |
curl -H "Authorization: Bearer sk_live_abc123" \
"https://api.pullfirst.com/v1/enforcement?filter=PenaltyAmount>10000&orderBy=PenaltyAmount%20desc"{
"data": [
{
"id": 42,
"companyName": "ABC Construction Inc.",
"dbaNames": ["ABC Builders"],
"individualNames": ["John Smith"],
"licenseNumbers": ["BC123456"],
"city": "Minneapolis",
"orderType": "Consent Order",
"actionsTaken": ["censured", "civil penalty"],
"penaltyAmount": 15000.00,
"orderDate": "2024-06-15",
"violationTypes": ["unlicensed work", "failure to supervise"]
}
],
"page": 1,
"pageSize": 20,
"totalCount": 52,
"totalPages": 3
}Retrieve a specific enforcement action.
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | Yes | Enforcement action ID |
All enforcement actions for a specific contractor.
| Name | Type | Required | Description |
|---|---|---|---|
| licenseNumber | string | Yes | The license number |
Most recent enforcement actions.
| Name | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Number of results (default: 10, max: 50) |
Aggregated enforcement data by year, action type, and violation type.
Federal workplace safety inspections and violations.
Search OSHA inspections by establishment name, city, or date range.
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | No | Establishment name |
| city | string | No | City |
| hasViolations | boolean | No | Filter to inspections with violations |
| fromDate | string | No | Inspection date range start (YYYY-MM-DD) |
| toDate | string | No | Inspection date range end (YYYY-MM-DD) |
| page | integer | No | Page number |
| pageSize | integer | No | Results per page |
curl -H "Authorization: Bearer sk_live_abc123" \
"https://api.pullfirst.com/v1/osha/search?name=Roofing&city=Minneapolis&hasViolations=true"Full inspection details including violations and penalties.
| Name | Type | Required | Description |
|---|---|---|---|
| activityNumber | integer | Yes | OSHA activity number |
OSHA database statistics — total inspections, violations, and penalties.
1.27M+ building permits across 50+ Minnesota jurisdictions.
Search stored permits by contractor name, city, or permit type.
| Name | Type | Required | Description |
|---|---|---|---|
| contractorName | string | No | Contractor name (fuzzy match) |
| city | string | No | Filter by city |
| permitType | string | No | Filter by permit type |
| page | integer | No | Page number |
| pageSize | integer | No | Results per page |
All permits pulled at a specific property address.
| Name | Type | Required | Description |
|---|---|---|---|
| address | string | Yes | Street address |
| city | string | No | City |
List of all jurisdictions with permit data and record counts.
Minnesota Attorney General contractor enforcement actions.
List AG enforcement actions with Gridify filtering.
| Name | Type | Required | Description |
|---|---|---|---|
| filter | string | No | Gridify filter expression |
| page | integer | No | Page number |
| pageSize | integer | No | Results per page |
AG enforcement actions for a specific contractor.
| Name | Type | Required | Description |
|---|---|---|---|
| licenseNumber | string | Yes | The license number |
Lookup tables for filtering.
All license types — Residential Contractors, Electrical, Plumbing, etc.
[
{ "id": 1, "name": "Residential Contractors", "code": "RC" },
{ "id": 2, "name": "Electrical", "code": "EL" }
]Detailed license categories within each type.
All license status values with isActive flag.
[
{ "id": 1, "name": "Issued", "isActive": true },
{ "id": 2, "name": "Expired", "isActive": false },
{ "id": 3, "name": "Revoked", "isActive": false }
]List endpoints support Gridify syntax for complex queries.
| Operator | Meaning | Example |
|---|---|---|
= | Equals | status=Issued |
!= | Not equals | status!=Expired |
=* | Contains | name=*Roofing* |
^ | Starts with | licenseNumber^BC |
> < >= <= | Comparison | expirationDate>2025-01-01 |
, | AND | city=Minneapolis,status=Issued |
| | OR | status=Revoked|status=Suspended |
/i | Case insensitive | name=*roofing/i |