Skip to content

PHP SDK Reference

PHP client for the Neuramancer fake-detection API. Every API endpoint has its own file containing a pure function you can import via require_once, or run directly as a CLI script.

Follow the Onboarding Guide to install dependencies and set up your environment before making API calls.

Run every E2E test included in your SDK package:

Terminal window
bash run_all_e2e.sh
OptionDescription
SKIP_ANALYSIS=1 bash run_all_e2e.shSkip the analysis_run_e2e test (fast check)

The script will:

  1. Run each *_e2e.php test sequentially
  2. Print a pass / fail / skip summary at the end
  3. Exit with code 1 if any test failed

Alternatively, you can run each individual *_e2e.php test in isolation.

Every file accepts -h / --help. Output is JSON and can be piped to jq:

Terminal window
# Create an analysis
php api_requests/create_analysis.php ./trial_images/fake.jpg width=720 height=960 | jq
# Create without upload (record only — upload separately, then start)
php api_requests/create_analysis.php ./trial_images/fake.jpg width=720 height=960 --no-upload | jq
# <analysis_id> stands for a 24-character hex ObjectId returned by the create_analysis call like this: 65a1b2c3d4e5f6a7b8c9d0e1
# Start analysis inference (after uploading separately)
php api_requests/start_analysis.php <analysis_id> | jq
# Get a single analysis
php api_requests/get_analysis.php <analysis_id> | jq
# Poll until complete
php api_requests/get_analysis.php <analysis_id> --poll 5 60 | jq
# List analyses
php api_requests/list_analyses.php search=invoice limit=10 | jq
# Delete
php api_requests/delete_analysis.php <analysis_id> | jq
# Retry with different options
php api_requests/retry_analysis.php <analysis_id> tier=forensicReporting | jq
# Tenant info
php api_requests/get_tenant.php | jq
php api_requests/update_tenant.php --s3-from-env | jq
php api_requests/get_tenant_report.php range 2025-01-01 2027-01-31 | jq
# API key management
php api_requests/get_apikeys.php | jq
php api_requests/create_apikey.php "Production Key" 365 | jq
php api_requests/delete_apikey.php <uuid> | jq
# Health / ping
php api_requests/health.php | jq
php api_requests/ping.php | jq

Include api_requests/autoload.php to load all request functions at once, or import individual files with require_once:

<?php
// Load all request functions
require_once __DIR__ . '/api_requests/autoload.php';
// Or import only what you need
// require_once __DIR__ . '/api_requests/create_analysis.php';
// require_once __DIR__ . '/api_requests/get_analysis.php';
// Create
$result = create_analysis(true, './trial_images/fake.jpg', [
'name' => 'my-image.jpg',
'filename' => 'my-image.jpg',
'format' => 'jpg',
'width' => 720,
'height' => 960,
'tier' => 'forensicReporting',
]);
$analysisId = $result['data'][0]['id'];
echo "Created in {$result['_meta']['durationMs']}ms\n";
// Poll until done
$final = poll_analysis($analysisId, 5, 60);
$analysis = $final['data'][0];
echo $analysis['inferenceStatus']['result']['decision'];

See ./demo_library_usage.php for a runnable example.

All SDK functions return the API response body 1:1 as an associative array, with one additional key _meta containing SDK-produced runtime metadata:

[
// -- API response body (1:1, varies by endpoint) --
'success' => true,
'data' => [ ... ],
// -- SDK metadata (optionally present) --
'_meta' => [
'durationMs' => 123.45, // Wall-clock time in milliseconds
'status' => 200, // HTTP status code
'error' => null, // Always null on success
],
]

All functions throw \RuntimeException on API errors (non-2xx status codes or connection failures). Wrap calls in try/catch to handle errors:

try {
$result = get_analysis('abc123');
} catch (\RuntimeException $e) {
echo "API error: " . $e->getMessage() . "\n";
}

create_analysis() adds extra fields to _meta when $upload = true (the default):

_meta keyTypeDescription
durationMsfloatTotal time (create + upload + finish)
statusintHTTP status of the create call
errornullAlways null on success
uploadResultarrayUpload response (success, status, duration_ms, error)
startAnalysisResultarrayStart-analysis API response body

Creates an analysis, uploads an image via a presigned URL, and finalises the upload (3-step flow).

When --no-upload is passed (or $upload = false in code), only step A is executed — the analysis record is created but no file is uploaded.

Terminal window
php create_analysis.php <image_path> width=<int> height=<int> \
[name=<string>] [format=<jpg|png>] \
[comment=<string>] [model=<string>] [decisionStrategy=<string>] \
[tier=<flagging|forensicReporting>] \
[seed=<int>] [--no-upload]

Function signature:

create_analysis(bool $upload = true, string $imagePath = '', array $options = []): array
ParameterRequiredDefaultDescription
$upload—trueWhether to upload and then start the analysis
$imagePathwhen $upload = true''Path to the image file
width✔—Image width in pixels (>64, ≤8192)
height✔—Image height in pixels (>64, ≤8192)
name—filenameDisplay name for the analysis
format—auto-detectjpg or png
comment—""Free-text comment
tags—[]Comma-separated tags
model—nais-image-latestInference model identifier
decisionStrategy—defaultdefault|pedantic|relaxed
tier—flaggingflagging or forensicReporting
seed—1337Random seed for inference reproducibility
--no-upload——Only create the record (skip upload + finalise)

tier defaults to "flagging". Set tier=forensicReporting for the full forensic result set. See Cost Model.

For S3-backed analyses, the API response includes storageUrls.objectKey for the uploaded input file and generated result files. This is the exact object path in the bucket.

Example:

bucket-hash/analysis-image-697fbb59f0630-857f5013877f5dbb5cb

If you split this value at /, the last segment is the filename in object storage:

analysis-image-697fbb59f0630-857f5013877f5dbb5cb

That filename suffix is a SHA-256 hash of a random UUID. It is generated intentionally so filenames do not collide in storage. For direct bucket access, always use the full storageUrls.objectKey, not only the final filename segment.

Retrieves a single analysis by ID (24-character hex ObjectId).

Terminal window
php get_analysis.php <analysis_id> [--poll [interval_sec] [max_attempts]]

Pass --poll to automatically poll until the analysis reaches completed or failed (default: 10 s interval, 30 max attempts).

Lists analyses with optional search and pagination.

Terminal window
php list_analyses.php [search=<string>] [start=<int>] [limit=<int>] [tenantName=<string>]
ParameterDefaultDescription
search—Free-text search over name and comment
start0Zero-based pagination offset
limit25Page size (≥ 1)
tenantName.envTenant name override

Soft-deletes an analysis by ID.

Terminal window
php delete_analysis.php <analysis_id>

Re-runs inference on an existing analysis, optionally with updated options.

Terminal window
php retry_analysis.php <analysis_id> \
[model=<string>] [decisionStrategy=<string>] \
[tier=<flagging|forensicReporting>] \
[seed=<int>]

Valid decisionStrategy values: default, pedantic, relaxed.

Confirms an analysis upload and triggers inference (after create_analysis() was called with --no-upload).

Terminal window
php start_analysis.php <analysis_id> [tenant_name]

Retrieves tenant details (storage config, masked API keys).

Terminal window
php get_tenant.php [tenantName]

Updates tenant settings. Pass --s3-from-env to populate S3 config from .env variables.

Terminal window
php update_tenant.php [--s3-from-env] [key=value ...]

🚨 DANGER: This overwrites existing tenant settings. Ensure your .env file reflects the intended state.

Get Tenant Report — get_tenant_report.php

Section titled “Get Tenant Report — get_tenant_report.php”

Retrieves a tenant usage report (total or date-range).

Terminal window
php get_tenant_report.php [total|range] [startTime] [endTime]
Terminal window
php get_apikeys.php [tenantName]
Terminal window
php create_apikey.php <key_name> <expiry_in_days>

⚠️ WARNING: The clear-text key is shown only once. Store it securely.

Terminal window
php delete_apikey.php <uuid>
ScriptDescription
ping.phpLightweight connectivity check (no auth required)
health.phpHealth check (no auth required) returning server uptime

The SDK ships integration tests that exercise full API workflows. They double as runnable usage examples.

ScriptAuthWorkflow
analysis_run_e2e.phpApiKeyRuns inference on fake.jpg (expects “fake”) and real.jpg (expects “real”), verifying classification for each.
apikey_crud_e2e.phpApiKeyCreate a temporary API key ⇒ list & verify ⇒ delete ⇒ verify removal.
list_analyses_e2e.phpApiKeyList analyses ⇒ search by name ⇒ paginate.
monitoring_e2e.phpApiKeyPing (no auth) ⇒ authenticated health check.
tenant_report_e2e.phpApiKeyGet tenant info ⇒ fetch total usage report.
update_tenant_e2e.phpApiKeyRead tenant ⇒ set test webhook URL ⇒ verify ⇒ restore original ⇒ verify.
analysis_lifecycle_e2e.phpApiKeyFull lifecycle: create (no upload) ⇒ manual upload ⇒ start ⇒ poll ⇒ get ⇒ list (search, pagination) ⇒ retry ⇒ poll ⇒ verify diff ⇒ delete ⇒ confirm 404.
Terminal window
# Run a single test
php analysis_run_e2e.php
# Run all tests
bash run_all_e2e.sh
TierDescription
flagging (default)Fast binary flag — returns only decision + confidence. Fields like predictions, heatmaps, pdfReportStorageUrls, text-content fields are null.
forensicReportingFull forensic analysis — all fields populated, PDF export available.

Set the tier when creating an analysis:

Terminal window
php api_requests/create_analysis.php image.jpg width=720 height=960 tier=forensicReporting
Terminal window
# Run 4 parallel create-and-poll cycles
bash run_benchmark.sh 4

Requires jq. See run_benchmark.sh for tuneable parameters.