Live ATF EZ Check verification
POST
/v1/ffl/{license_number}/verify
const url = 'https://api.oldsteelarsenal.com/v1/ffl/example/verify';const options = { method: 'POST', headers: { 'x-client-id': '<x-client-id>', 'x-signature': '<x-signature>', 'x-timestamp': '<x-timestamp>', 'Content-Type': 'application/json' }, body: '{"force":false}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.oldsteelarsenal.com/v1/ffl/example/verify \ --header 'Content-Type: application/json' \ --header 'x-client-id: <x-client-id>' \ --header 'x-signature: <x-signature>' \ --header 'x-timestamp: <x-timestamp>' \ --data '{ "force": false }'Cache-first verification against ATF’s public EZ Check form, shared by every client of this service.
- Cache: answers fresher than the TTL (default 24h) are served with
cached: trueand cost nothing. Cache lookup uses the stable licence identity. NotFound answers are cached too. - Budget: only real calls to ATF spend budget, and it is charged in two tiers — your tenant’s hourly allowance (default 30/h) and a service-wide ceiling shared by all tenants (default 120/h). Either one exhausted → 429, with the
detailnaming which tier (tenant …vsservice …); retry next hour or accept the cached answer. force: true: skip the cache read (still refreshes it) — the only way a cached licence spends budget.- Returns the real expiry date and a structured premise address (street/street2/city/state/zip) parsed server-side.
- ATF unreachable or unparsable → 502; fall back to your own cached copy.
Scope: ffl:verify.
Authorizations
Section titled “Authorizations”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters”license_number
required
License Number
string
Header Parameters
Section titled “Header Parameters”Request Body
Section titled “Request Body”Media typeapplication/json
Any of:
VerifyRequest
object
force
Force
boolean
null
Responses
Section titled “ Responses ”Successful Response
Media typeapplication/json
VerifyResponse
object
cached
required
Cached
True when served from the shared cache (no ATF call, no budget spent).
boolean
fetched_at
required
Fetched At
When this answer was fetched from ATF (UTC).
string format: date-time
ffl_number
required
Ffl Number
Licence number as submitted.
string
found
required
Found
boolean
status
required
Status
‘Verified’ | ‘Expired’ | ‘NotFound’.
string
Examplegenerated
{ "address": "example", "cached": true, "city": "example", "expiry_date": "2026-04-15", "fetched_at": "2026-04-15T12:00:00Z", "ffl_number": "example", "found": true, "license_type": "example", "licensee_dba": "example", "licensee_name": "example", "state": "example", "status": "example", "street": "example", "street2": "example", "zip": "example"}Missing/invalid HMAC auth
Missing ffl:verify
Validation Error
Media typeapplication/json
HTTPValidationError
object
detail
Detail
Array<object>
ValidationErrorobject
ctx
Context
object
input
Input
loc
required
Location
Array
msg
required
Message
string
type
required
Error Type
string
Examplegenerated
{ "detail": [ { "ctx": {}, "input": "example", "loc": [ "example" ], "msg": "example", "type": "example" } ]}Tenant or service hourly ATF budget exhausted
ATF unreachable or response unparsable
