Developer guide

Canadian sanctions API in PHP: company screening

Screen suppliers with the Canadian sanctions API in PHP. Select the autonomous list and keep bilingual names and company IDs with the result.

250 free live screenings. One lifetime allowance. No credit card required.
On this page

Check Canadian companies from PHP

Identify the legal organization behind the customer account and keep its registry or identifier context. Preserve identifier values as strings when leading zeros or formatting carry meaning. A trading name should not silently replace the legal entity simply because it is easier to display on an invoice.

For an invented bilingual company record, keep the source of each name form and submit only supported subject fields. The reviewer needs the original candidate and comparable identity facts. The application should describe the selected ca-autonomous scope rather than presenting one comparison as a complete Canadian compliance decision.

Prepare the synthetic exercise

The invented Example Harbor Trading organization demonstrates a supplier check rather than a person check. Keep entityType as organization and preserve registration values as strings in your form model. A leading zero is data, not formatting for PHP to discard.

PHP setup and request files
RequirementValue or action
RuntimeUse PHP 8.2 or later with the cURL extension enabled. Run the script in a backend or trusted CLI. This example does not require Composer or a provider SDK.
Client fileSave the client as screen.php
Screening endpointPOST /api/v1/screenings
SANCTIONSKIT_API_KEYSandbox key; screenings:write and results:read scopes
SCREENING_OPERATION_IDPersist one operation ID; reuse only with the identical request body
request.jsonExample Harbor Trading: invented subject; sandbox@1: synthetic records
request.json: synthetic sandbox request
{
  "subject": {
    "name": "Example Harbor Trading",
    "entityType": "organization"
  },
  "package": "sandbox@1",
  "retention": "standard"
}

Implement the PHP request boundary

Use cURL behind the authenticated supplier controller, with the legal organization already established. Keep invoice display names separate from supported subject fields. If you add registry identifiers, include only facts you actually hold and preserve their scheme and provenance.

PHP: authenticated screening client
<?php
// PHP 8.2+, ext-curl. Run in a backend or trusted CLI, never in browser code.
declare(strict_types=1);
try {
    $key = getenv('SANCTIONSKIT_API_KEY') ?: '';
    $operation = getenv('SCREENING_OPERATION_ID') ?: '';
    if ($key === '' || $operation === '') throw new RuntimeException('Set the API key and a persistent operation ID.');
    $raw = file_get_contents($argv[1] ?? 'request.json');
    if ($raw === false || strlen($raw) > 65536) throw new RuntimeException('Request file is missing or too large.');
    $body = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
    if (!is_array($body) || !isset($body['subject']) || (array_key_exists('sources', $body) === array_key_exists('package', $body))) {
        throw new RuntimeException('Supply a subject and exactly one of sources or package.');
    }
    $received = '';
    $curl = curl_init('https://www.sanctionskit.com/api/v1/screenings');
    if ($curl === false) throw new RuntimeException('Unable to initialize HTTP client.');
    curl_setopt_array($curl, [
        CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($body, JSON_THROW_ON_ERROR),
        CURLOPT_HTTPHEADER => ['Authorization: Bearer '.$key, 'Content-Type: application/json', 'Idempotency-Key: '.$operation],
        CURLOPT_FOLLOWLOCATION => false, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 25,
        CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_WRITEFUNCTION => static function ($handle, string $chunk) use (&$received): int {
            if (strlen($received) + strlen($chunk) > 8 * 1024 * 1024) return 0;
            $received .= $chunk;
            return strlen($chunk);
        },
    ]);
    $ok = curl_exec($curl);
    $status = (int) curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    if ($ok === false) throw new RuntimeException('Transport failed or response exceeded size limit.');
    $envelope = json_decode($received, false, 512, JSON_THROW_ON_ERROR);
    if ($status < 200 || $status >= 300) throw new RuntimeException('Screening incomplete: HTTP '.$status.'.');
    $data = is_object($envelope) ? ($envelope->data ?? null) : null;
    if (!is_object($data) || !is_string($data->id ?? null) || $data->id === '' ||
        !in_array($data->status ?? null, ['potential_match', 'no_match'], true) ||
        !is_array($data->matches ?? null)) {
        throw new RuntimeException('Incomplete response: unexpected screening shape.');
    }
    $count = count($data->matches);
    if (($data->status === 'no_match' && $count !== 0) || ($data->status === 'potential_match' && $count === 0)) {
        throw new RuntimeException('Incomplete response: inconsistent screening shape.');
    }
    echo json_encode(['id' => $data->id, 'status' => $data->status, 'candidateCount' => $count], JSON_THROW_ON_ERROR).PHP_EOL;
} catch (Throwable $error) {
    // No raw response, submitted identity, or credential is logged.
    fwrite(STDERR, 'Screening did not complete: '.get_class($error).'. Check the operation before retrying.'.PHP_EOL);
    exit(1);
}

Run the client

Run the sandbox request
php screen.php request.json

Confirm Canadian sanctions scope before production

The PHP request targets ca-autonomous, not every Canadian sanctions regime. Name the autonomous scope in the supplier record and inspect the underlying regulation for a potential candidate. A company’s trading label alone is not evidence that it is the listed legal entity.

Production source-discovery contract
CheckRequired evidence
GET /api/v1/sourcesProduction key with sources:read; response data array
idca-autonomous
availability / freshavailable / true
capabilitiesContains the requested subject.entityType
currentVersionActive version; retrieved_at and last_checked_at are not publication dates
lastImportMay describe an import that is not the active version
Missing or ineligible sourceInspect disabledReason; required coverage stays incomplete
Displayed clientAdd these discovery checks before its production call
Read source discovery with your production key
curl --fail-with-body --max-time 25 --header "Authorization: Bearer $SANCTIONSKIT_API_KEY" "https://www.sanctionskit.com/api/v1/sources"

Select ca-autonomous in the production request

Explicit change from the sandbox exercise
SettingProduction request
KeySeparate production credential with screenings:write
Coveragesources: ["ca-autonomous"]; omit package
Operation IDNew ID for the changed body and environment
UsageProduction access and screening allowance apply
SubjectOnly lawfully held, known identifying facts; no invented date precision
request.json: explicit ca-autonomous selection
{
  "subject": {
    "name": "Example Harbor Trading",
    "entityType": "organization"
  },
  "sources": [
    "ca-autonomous"
  ],
  "retention": "standard"
}

Interpret Canadian sanctions evidence in this workflow

Link data.id and data.coverage to the supplier’s internal reference. Keep bilingual source names and available company identifiers with the candidate. The review should explain the legal-entity comparison rather than merely copying the invoice name into a sanctioned flag.

Canadian sanctions candidate fields to retain
Fields in data.matches[]Review use
record.id and record.sourceIdKeep the autonomous-list record reference with the returned candidate.
record.designations[].legalReferences and wordingShow the available regulation and published designation context; consult the regulation when reviewing applicable restrictions.
record.names and identifiersKeep bilingual or alternative names and registration details as returned, with missing evidence visibly unknown.
  • data.id; data.coverage; data.versions; supplied disclaimer
  • data.matches[]: record, assessment, evidence, conflicts
  • GET /api/v1/results/{id}: results:read scope
  • Retained evidence and case review

Verify the application behavior

Recovery rules for the same saved operation
ConditionNext action
401 / 403Correct credentials or scopes before retrying
coverage_unavailable / stale_coverageKeep required coverage incomplete; no silent source substitution
Timeout after submissionRecover with the original Idempotency-Key and identical body
409Investigate an operation-key conflict
429 / 503Follow the specific error and Retry-After; an allowance cap may require a plan or usage change
Contract and safe diagnostic references
Operational reference
ReferenceUse
error.code / error.requestIdSafe recovery diagnostics; never log the submitted subject, key or full candidate response
potential_match / no_matchCompleted comparison outcomes; neither is an automatic business approval
  • Preserve a synthetic registration value with a leading zero.
  • Keep an invoice label separate from the legal organization name.
  • Reject an error response without marking the supplier check complete.

Sources and references

Frequently asked questions

Why does the Canadian PHP example preserve company IDs as strings?

Identifiers may contain leading zeros or nonnumeric characters that carry meaning. Retain the value and scheme from the source rather than coercing a company reference into an integer for convenience.

Is a Canadian supplier trading name enough for the PHP request?

Identify the legal subject behind the account first. A trading name can be useful context, but it should not silently replace the organization whose identity and relevant registration evidence your process has established.

Why does the Canadian PHP example use a company rather than a person?

It demonstrates an organization check with a fictional trading company. Use the correct entityType and only the registration details or identifiers you know. Retain alternative or bilingual source names as returned rather than forcing them into one name field.

What does the fictional PHP company example establish about Canadian coverage?

It tests organization-shaped request handling in sandbox. It does not test the current Canadian source or determine any company’s legal status. Production discovery and the selected autonomous-list scope remain separate checks.