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:

  1. Reads your API bearer token from an environment variable.
  2. Asks the ISA underwriting engine whether John Doe qualifies for Final Expense coverage.
  3. 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

RequirementWhy
PHP 8.2 or newerThe SDK uses readonly classes and backed enums introduced in PHP 8.1; 8.2 is the minimum tested version.
Composer v2Package manager for PHP. Install at https://getcomposer.org/download/
An ISA API bearer tokenSee "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/sdk

3. 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.php

4. 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:

FieldMeaning
$result->requestIdServer-minted correlation ID. Copy this into every support ticket or log entry.
$result->idempotencyKeyUUID the SDK sent on the Idempotency-Key header.
$result->plansOne entry per product — flat plans list.
$offer->carrier->nameCarrier display name (e.g., Aetna Accendo).
$offer->product->nameCarrier-formatted product name.
$offer->product->idStable prod_<uuid> — use this to carry a selection into a quote.
$row->eligibility->categoryClosed enum: immediate / graded / rop.
$row->premium->amount->centsInteger US cents — the canonical numeric value.
$row->premium->amount->displayVerbatim 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

  1. Switch the token:

    export ISA_TOKEN="<your isa_live_… token>"
  2. No code changes needed. Isa::withBearer() reads the same env var.

  3. Rate limits differ. Review rate limits before launching.


What's next

TopicWhere to look
Prequalify deep divePrequalify guide
WebhooksWebhooks guide
Token rotationAuthentication guide
Full API referenceAPI Reference