PHP: Zero to first 200
A PHP 8.2 script that prequalifies John Doe for Final Expense coverage. Under 60 minutes for a backend developer with no insurance domain knowledge.
PHP: Zero to first 200
Target: A CLI script that prequalifies John Doe (NC, 64, male, no conditions) for Final Expense coverage and prints every qualifying plan with its monthly premium. Time budget: under 60 minutes from a blank directory.
Language requirement: PHP 8.2+ with Composer.
What you'll build
A single PHP script — prequalify.php — that:
- Reads your API bearer token from an environment variable.
- Asks the ISA underwriting engine whether John Doe qualifies for Final Expense coverage.
- Prints each qualifying plan: carrier name, plan tier, monthly premium, and face value.
"Prequalify" is a fast eligibility screen. You send an applicant's demographics and a coverage request; the engine returns every plan the applicant qualifies for with a bucketed monthly premium. It is not a binding quote.
"Final Expense" (FEX) is a small face-value whole-life product — typically $5,000–$25,000 death benefit — designed to cover end-of-life costs.
Prerequisites
| Requirement | Why |
|---|---|
| PHP 8.2 or newer | The SDK uses readonly classes and backed enums introduced in PHP 8.1; 8.2 is the minimum tested version. |
| Composer v2 | Package manager for PHP. Install at https://getcomposer.org/download/ |
| An ISA API bearer token | See "Getting your test token" below. |
Getting your test token
Your ISA API token arrives by email within minutes of completing checkout at
checkout.isaapi.com. The email contains both an
isa_test_… and an isa_live_… token. Set the test token as an environment
variable:
export ISA_TOKEN="<paste your isa_test_… key here>"Test vs live. Every call made with a test token runs against the real engine with real carrier rules, but no binding decisions are issued. Switch to your live token when you are ready to ship.
1. Create a project directory
mkdir isa-php-demo && cd isa-php-demo
composer init --no-interaction --name="my-org/isa-demo" --type="project"2. Install the SDK
composer require isa-sdk/sdk3. Hello world
Create prequalify.php:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use Isa\Sdk\Isa;
use Isa\Sdk\Zyins\Applicant;
use Isa\Sdk\Zyins\Coverage;
use Isa\Sdk\Zyins\Height;
use Isa\Sdk\Zyins\NicotineUsage;
use Isa\Sdk\Zyins\Sex;
use Isa\Sdk\Zyins\Weight;
use Isa\Sdk\Zyins\Reference\PrequalifyRequest;
use Isa\Sdk\Catalog\Products;
use Isa\Sdk\Zyins\Exception\IsaConfigException;
use Isa\Sdk\Zyins\Exception\IsaException;
// Isa::withBearer() reads ISA_TOKEN from the environment.
// If missing, it throws IsaConfigException with a clear message.
try {
$isa = Isa::withBearer();
} catch (IsaConfigException $e) {
fwrite(STDERR, 'Configuration error: ' . $e->getMessage() . PHP_EOL);
fwrite(STDERR, 'Set ISA_TOKEN in your environment.' . PHP_EOL);
exit(1);
}
// Products::fex()->aetnaAccendo() carries the stable prod_<uuid> used on the wire.
// Always use catalog constants — never hardcode prod_ strings or slugs.
$result = $isa->zyins->prequalify->run(new PrequalifyRequest(
applicant: new Applicant(
dob: '1962-04-18',
sex: Sex::Male,
height: Height::fromFeetInches(5, 10), // 5 feet 10 inches
weight: Weight::fromPounds(195),
state: 'NC',
nicotineUse: NicotineUsage::None,
),
coverage: Coverage::faceValue(25_000),
products: [Products::fex()->aetnaAccendo()],
));
foreach ($result->plans as $offer) {
foreach ($offer->pricing as $row) {
if ($row->primary && $row->premium !== null) {
printf(
" %-24s %-40s category=%-10s premium=%-10s (%d cents)\n",
$offer->carrier->name,
$offer->product->name,
$row->eligibility->category?->value ?? 'n/a',
$row->premium->amount->display,
$row->premium->amount->cents,
);
}
}
}Run it:
php prequalify.php4. Inspect the response
What you should see:
Aetna Accendo Aetna Accendo Final Expense category=immediate premium=$87.42 (8742 cents)
The exact plans and premiums vary by which carriers are enabled on your account.
What the response fields mean:
| Field | Meaning |
|---|---|
$result->requestId | Server-minted correlation ID. Copy this into every support ticket or log entry. |
$result->idempotencyKey | UUID the SDK sent on the Idempotency-Key header. |
$result->plans | One entry per product — flat plans list. |
$offer->carrier->name | Carrier display name (e.g., Aetna Accendo). |
$offer->product->name | Carrier-formatted product name. |
$offer->product->id | Stable prod_<uuid> — use this to carry a selection into a quote. |
$row->eligibility->category | Closed enum: immediate / graded / rop. |
$row->premium->amount->cents | Integer US cents — the canonical numeric value. |
$row->premium->amount->display | Verbatim carrier-formatted string (e.g. $87.42). |
5. Handle errors
The SDK throws a hierarchy of typed exceptions. Catch the specific subclasses:
<?php
use Isa\Sdk\Zyins\Exception\IsaValidationException;
use Isa\Sdk\Zyins\Exception\IsaRateLimitException;
use Isa\Sdk\Zyins\Exception\IsaIdempotencyConflictException;
use Isa\Sdk\Zyins\Exception\IsaException;
try {
$result = $isa->zyins->prequalify->run($request);
} catch (IsaValidationException $e) {
// 400 — fix your request; do not retry.
fwrite(STDERR, 'Validation error: ' . $e->getMessage() . PHP_EOL);
} catch (IsaRateLimitException $e) {
// 429 — honor the retry-after window.
$wait = $e->retryAfterSeconds() ?? 60;
fwrite(STDERR, "Rate limited. Wait {$wait}s before retrying." . PHP_EOL);
} catch (IsaIdempotencyConflictException $e) {
// 409 — bug in your retry logic. Log and alert; do NOT automatically retry.
fwrite(STDERR, 'Idempotency conflict on key: ' . $e->getKey() . PHP_EOL);
} catch (IsaException $e) {
// Any other API error.
fwrite(STDERR, 'API error [' . $e->code() . ']: ' . $e->getMessage() . PHP_EOL);
if ($e->requestId() !== null) {
fwrite(STDERR, 'Request ID: ' . $e->requestId() . PHP_EOL);
}
}6. Add idempotency
The SDK auto-generates a UUID v4 idempotency key for every call. For cross-process replay safety, pass a stable key at dispatch time:
use Isa\Sdk\Zyins\RequestOptions;
$idempotencyKey = '550e8400-e29b-41d4-a716-446655440000'; // UUID v4
$options = RequestOptions::default()->withIdempotencyKey($idempotencyKey);
$result = $isa->zyins->prequalify->run($request, $options);7. Move to live mode
-
Switch the token:
export ISA_TOKEN="<your isa_live_… token>" -
No code changes needed.
Isa::withBearer()reads the same env var. -
Rate limits differ. Review rate limits before launching.
What's next
| Topic | Where to look |
|---|---|
| Prequalify deep dive | Prequalify guide |
| Webhooks | Webhooks guide |
| Token rotation | Authentication guide |
| Full API reference | API Reference |
Updated about 11 hours ago