Skip to main content

Working with Children Checks (WWC)

This comprehensive guide shows you how to integrate Working with Children (WWC) checks across all Australian states and territories using the Oho API.

Overview

The /api/scan endpoint provides a unified interface for submitting Working With Children (WWC) credential validations across all Australian states and territories. Validations are processed asynchronously - the endpoint queues the request and returns immediately with a correlation_id for tracking. Results are delivered later via webhook.

This universal endpoint accepts a consistent payload structure across all states, with the type field specifying which state registry to validate against. This approach eliminates the need to maintain separate integration code for each state.

Base URL: POST /api/scan

Authentication: Required (Bearer token)

Content-Type: application/json

Key Benefits:

  • ✅ Single endpoint for all Australian states and territories
  • ✅ Consistent payload structure across all WWC types
  • ✅ Asynchronous processing for high performance
  • ✅ Built-in retry logic and webhook delivery
  • ✅ Idempotency support for reliable integrations

Understanding State Capabilities

Before integrating WWC verification, it's important to understand that capabilities vary significantly by state. This affects verification speed, monitoring frequency, and available features.

Quick Capability Overview

StateVerification SpeedMonitoring FrequencyEmployer LinkageRenewal Auto-Updates
VIC<10 secondsWeeklyNo (employee responsibility)Yes
NSWHoursAnnual + direct OCG alertsYes (automatic)Yes
QLD<10 secondsWeeklyYes (manual)No
SA<10 minutesWeeklyYes (automatic)Yes
WA<10 secondsWeeklyNoYes
TAS<10 minutesWeeklyNoYes
NT<10 minutesWeeklyNoYes
ACTMonthly (manual)MonthlyNoYes
Need Detailed Capability Information?

See the WWCC Capability Reference for detailed scenarios including:

  • Verification timeframes and response types by state
  • Employer linkage establishment
  • Monitoring and notification timing
  • Pause/resume monitoring behavior
  • Renewal handling approaches

Getting Started

Prerequisites

Before submitting WWC validations, ensure:

  1. Active organization account - Your organization must be active and in good standing
  2. Verified user status - Your API user must have completed email verification
  3. Constituents created (optional) - If linking to existing constituents, they must exist in your organization first

Universal Payload Structure

This endpoint uses a single, standardized payload structure for all WWC types. Simply change the type field to target different states - the rest of the structure remains consistent:

{
"type": "vicwwc|nswwwc|qldblue|qldblueex|sawwc|wawwc|taswwc|ntwwc|actwwc",
"identifier": "WWC_CARD_NUMBER",
"first_name": "First",
"middle_name": "Middle (optional)",
"surname": "Last",
"birth_date": "YYYY-MM-DD",
"alternate_name": "Previous Name (optional)",
"expiry": "YYYY-MM-DD (optional, required for QLD)",
"constituent": {
"id": 123
}
}

Field Descriptions

FieldTypeDescriptionRequired StatesOptional States
typestringCheck type code (see table below)All states-
identifierstringWWC card or application numberAll states-
first_namestringFirst/given nameAll states-
middle_namestringMiddle name(s)-All states
surnamestringSurname/family nameAll states-
birth_datestring (YYYY-MM-DD)Date of birthNSW, SAVIC, QLD, WA, TAS, NT, ACT
expirystring (YYYY-MM-DD)Expiry date (must be future)QLD (both types)VIC, WA (optional)
alternate_namestringMaiden/previous name-VIC, QLD, WA
constituent.idintegerLink to existing constituent-All states (recommended)

Supported Check Types

Each state has a specific type code to use in the payload:

State/TerritoryType Codebirth_dateAge CheckSpecial Notes
VictoriavicwwcOptionalNoneSupports alternate_name
New South WalesnswwwcRequired18+ (3mo grace)Auto-detects APP numbers
QueenslandqldblueOptionalNoneRequires expiry (future date)
Queensland ExemptionqldblueexOptionalNoneRequires expiry for exemptions
South AustraliasawwcRequired10+-
Western AustraliawawwcOptionalNoneSupports alternate_name, expiry
TasmaniataswwcOptionalNone-
Northern TerritoryntwwcOptionalNone-
ACTactwwcOptionalNone-

Correlation ID & Idempotency

What is a Correlation ID?

A correlation_id is a unique identifier that tracks your scan request from submission through to webhook delivery. You can either:

  1. Let the API generate one (recommended for most cases) - returned in the response
  2. Provide your own in the request payload for idempotency

Idempotent Requests

To prevent duplicate scans, provide your own correlation_id in the request:

{
"type": "vicwwc",
"identifier": "1076131A",
"first_name": "Cameron",
"surname": "Schafer",
"birth_date": "1985-06-15",
"constituent": {
"id": 113767
},
"correlation_id": "my-unique-id-12345"
}

Idempotency behavior:

  • If you submit the same correlation_id multiple times, only the first request is processed
  • Subsequent requests with the same correlation_id return the existing correlation data
  • This prevents accidental duplicate scans if your request is retried due to network issues

Tracking Requests

Use the correlation_id to:

  1. Match webhook responses to your original requests
  2. Debug issues by providing the ID to support
  3. Query scan status via the status endpoint (if available)
  4. Implement idempotent operations in your integration

Identifier Formats

Each state has specific format requirements for WWC card numbers and application numbers:

Victoria (type: "vicwwc")

  • Format: 7 digits + 1 letter (e.g., 1076131A)
  • Example: 1076131A, 2345678B

New South Wales (type: "nswwwc")

  • Card Number Format: WWC + 7 digits + 1 letter (e.g., WWC0157654E)
  • Application Number Format: APP + 7 digits (e.g., APP1234567)
  • Auto-detection: The API automatically detects whether you're submitting a card number or application number
  • Example: WWC0157654E (card), APP1234567 (application)

Queensland (type: "qldblue" or "qldblueex")

  • Standard Blue Card: Typically numeric with optional / separator (e.g., 123456/1), use type: "qldblue"
  • Exemption Card: May include prefix EX (e.g., EX123456), use type: "qldblueex"
  • Example: 123456/1 (standard), EX123456 (exemption)

South Australia (type: "sawwc")

  • Format: 8 digits
  • Example: 12345678

Western Australia (type: "wawwc")

  • Format: WWC prefix + digits (e.g., WWC987654321)
  • Example: WWC987654321

Tasmania (type: "taswwc")

  • Format: State-specific identifier
  • Example: TAS123456

Northern Territory (type: "ntwwc")

  • Format: State-specific identifier
  • Example: NT987654

Australian Capital Territory (type: "actwwc")

  • Format: State-specific identifier
  • Example: ACT111222

Note: While we provide common formats above, the API performs server-side validation. If you receive an identifier format error, verify the number directly with the issuing state authority.


Quick Start Examples

Victoria WWC

curl -X POST https://app.weareoho.com/api/scan \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "vicwwc",
"identifier": "1076131A",
"first_name": "Cameron",
"middle_name": "James",
"surname": "Schafer",
"alternate_name": "Cameron Smith",
"constituent": {
"id": 113767
}
}'

Success Response:

{
"correlation_id": "550e8400-e29b-41d4-a716-446655440000"
}

New South Wales WWC

Standard card number:

{
"type": "nswwwc",
"identifier": "WWC0157654E",
"first_name": "Jane",
"middle_name": "Mary",
"surname": "Doe",
"birth_date": "1985-03-15",
"constituent": {
"id": 113767
}
}

Application number (auto-detected):

{
"type": "nswwwc",
"identifier": "APP1234567",
"first_name": "John",
"middle_name": "Paul",
"surname": "Smith",
"birth_date": "1990-06-20",
"constituent": {
"id": 113768
}
}

Important: NSW requires birth_date and validates age is 18+ with a 3-month grace period (accepts applicants who will turn 18 within 3 months)


Queensland Blue Card

Standard Blue Card:

{
"type": "qldblue",
"identifier": "123456/1",
"first_name": "Michael",
"middle_name": "Andrew",
"surname": "Williams",
"alternate_name": "Mike Williams",
"expiry": "2026-12-31",
"constituent": {
"id": 113800
}
}

Blue Card Exemption:

{
"type": "qldblueex",
"identifier": "EX123456",
"first_name": "Sarah",
"middle_name": "Jane",
"surname": "Thompson",
"expiry": "2025-06-30",
"constituent": {
"id": 113801
}
}

Important:

  • QLD Blue Card requires expiry field (must be a future date)
  • Use type: "qldblue" for regular cards or type: "qldblueex" for exemptions
  • birth_date is optional but recommended

South Australia WWC

{
"type": "sawwc",
"identifier": "12345678",
"first_name": "David",
"middle_name": "Wei",
"surname": "Lee",
"birth_date": "1988-11-30",
"constituent": {
"id": 113769
}
}

Important:

  • SA requires birth_date and validates age is 10+
  • SA WWCC requires a middle name to be included in the full_name field (provided as first_name, middle_name, surname)

Western Australia WWC

{
"type": "wawwc",
"identifier": "WWC987654321",
"first_name": "Michael",
"middle_name": "Thomas",
"surname": "Brown",
"alternate_name": "Mike Brown",
"expiry": "2027-08-22",
"constituent": {
"id": 113770
}
}

Tasmania WWC

{
"type": "taswwc",
"identifier": "TAS123456",
"first_name": "Emma",
"middle_name": "Rose",
"surname": "Wilson",
"constituent": {
"id": 113771
}
}

Northern Territory WWC

{
"type": "ntwwc",
"identifier": "NT987654",
"first_name": "Robert",
"middle_name": "Li",
"surname": "Chen",
"constituent": {
"id": 113772
}
}

Australian Capital Territory WWC

{
"type": "actwwc",
"identifier": "ACT111222",
"first_name": "Sarah",
"middle_name": "Elizabeth",
"surname": "Johnson",
"constituent": {
"id": 113773
}
}

Linking to Existing Constituents

The API supports three workflows for managing WWC accreditations:

When you want to associate the WWC check with a person already in your system:

{
"type": "vicwwc",
"identifier": "1076131A",
"first_name": "Cameron",
"surname": "Schafer",
"birth_date": "1985-06-15",
"constituent": {
"id": 113767
}
}

Behavior:

  • ✅ Links accreditation to constituent ID 113767
  • ✅ Accreditation appears in constituent's profile
  • ✅ Auto-updates constituent with birth_date, mobile_number, email if those fields are null
  • ❌ Returns 400 error if constituent ID doesn't exist in your organization

When to use:

  • You have a constituent database and want to track WWC checks against people
  • You need to see all accreditations for a specific person
  • You want centralized compliance tracking

Scenario 2: Standalone Accreditation (No Constituent)

When you only want to validate credentials without linking to a person record:

{
"type": "vicwwc",
"identifier": "1076131A",
"first_name": "Cameron",
"surname": "Schafer",
"birth_date": "1985-06-15"
}

Behavior:

  • ✅ Creates standalone accreditation record
  • ✅ Validates credentials against registry
  • ✅ Stores result in your organization
  • ⚠️ Not linked to any constituent profile
  • ⚠️ Can be linked later via the UI or API

When to use:

  • Quick one-off validations
  • You don't maintain a constituent database
  • Validating external contractors or visitors
  • Testing/development

Scenario 3: Invalid Constituent ID (Error)

When you provide a constituent ID that doesn't exist:

{
"type": "vicwwc",
"identifier": "1076131A",
"first_name": "Cameron",
"surname": "Schafer",
"constituent": {
"id": 999999
}
}

Response (400 Bad Request):

{
"status": 400,
"message": "Validation error",
"errors": {
"constituent": {
"id": ["Constituent doesn't exist in your organization"]
}
}
}

How to avoid:

  1. Create the constituent first using POST /api/constituents
  2. Then submit the scan with the returned constituent ID
  3. Or omit constituent entirely for standalone accreditation

Webhook Configuration

Since the /api/scan endpoint processes requests asynchronously, results are delivered to your webhook endpoint when validation completes.

Setting Up Your Webhook

Configure your webhook URL:

  1. Log in to your Oho account
  2. Navigate to SettingsWebhooksScan Results
  3. Enter your webhook endpoint URL (must be HTTPS)
  4. Save and verify the endpoint

Webhook endpoint requirements:

  • Must be publicly accessible via HTTPS (HTTP not supported for security)
  • Should respond with 200 OK within 10 seconds
  • Must handle idempotent delivery (same result may be sent multiple times)

Webhook Payload Structure

When a scan completes, we POST the following JSON to your webhook:

{
"event": "accreditation_validation",
"correlation_id": "a8f5d2e1-3c4b-4d5e-8f9a-1b2c3d4e5f6a",
"message_id": 12345,
"content": {
"notification_type": "accreditation-result",
"org_id": 123,
"previous": null,
"current": {
"id": 5354,
"identifier": "1076131A",
"type": "vicwwc",
"status": "active",
"status_flags": {
"current": true,
"may_engage": true,
"expired": false,
"expiring": false
},
"registry_response": {
"may_engage": true,
"response": ["Current", "May Engage"],
"oho_status": "active",
"card_type": "employee_wwc"
}
},
"constituent": {
"id": 113767,
"first_name": "Cameron",
"surname": "Schafer",
"email": "cameron@example.com",
"organization": {
"id": 123,
"name": "Organization Name",
"abn": "12345678901",
"is_active": true
}
},
"entity_type_id": 3,
"event_type_id": 2,
"changed_fields": null
}
}

Key webhook fields:

  • correlation_id - Matches the UUID from your scan request
  • content.current - Contains the complete accreditation details
  • content.previous - Previous state (null for new checks, populated for updates)
  • content.constituent - Details about the person checked

Status Values

The content.current.status field indicates the check result:

StatusDescription
activeValid and current clearance
inactiveClearance expired or revoked
suspendedClearance temporarily suspended
cancelledClearance cancelled

The content.current.status_flags object provides detailed state information:

FlagDescription
currentWhether the clearance is currently valid
may_engageWhether the person is authorized to work with children
expiredWhether the clearance has expired
expiringWhether the clearance is expiring soon

Error Webhook Example

When validation fails, the webhook contains error details:

{
"event": "accreditation_validation",
"correlation_id": "b9e8d5f2-4c3a-5d6e-9f0a-2b3c4d5e6f7a",
"message_id": 12346,
"content": {
"notification_type": "accreditation-result",
"org_id": 123,
"previous": null,
"current": {
"id": null,
"identifier": "INVALID123",
"type": "nswwwc",
"status": "error",
"error": {
"message": "Invalid WWC number or details do not match",
"code": "VALIDATION_FAILED"
}
},
"constituent": {
"id": 113768,
"first_name": "Jane",
"surname": "Smith"
},
"entity_type_id": 3,
"event_type_id": 2,
"changed_fields": null
}
}

Webhook Security

Verifying webhook authenticity:

  1. All webhooks include an X-Hub-Signature header with HMAC-SHA1 signature in format sha1=<hex>
  2. Use your webhook secret (not API key) to verify the signature matches the payload
  3. Reject webhooks with invalid or missing signatures

Example verification (Node.js):

const crypto = require('crypto');

function verifyWebhook(payloadBody, signatureHeader, secret) {
// Extract the hex signature from "sha1=<hex>" format
const signature = signatureHeader.replace('sha1=', '');

// Compute HMAC-SHA1 of the raw payload body
const hmac = crypto.createHmac('sha1', secret);
hmac.update(payloadBody);
const expectedSignature = hmac.digest('hex');

// Use timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}

// Example usage in Express
app.post('/webhook', express.text({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-hub-signature'];
const secret = process.env.WEBHOOK_SECRET;

if (!verifyWebhook(req.body, signature, secret)) {
return res.status(401).send('Invalid signature');
}

const payload = JSON.parse(req.body);
// Process webhook...
res.status(200).send('OK');
});

Python example:

import hmac
import hashlib

def verify_webhook(payload_body: str, signature_header: str, secret: str) -> bool:
# Extract hex signature from "sha1=<hex>" format
signature = signature_header.replace('sha1=', '')

# Compute HMAC-SHA1
expected = hmac.new(
secret.encode('utf-8'),
payload_body.encode('utf-8'),
hashlib.sha1
).hexdigest()

# Use constant-time comparison
return hmac.compare_digest(expected, signature)

Retry Logic

If your webhook endpoint is unreachable or returns an error:

  • We retry up to 5 times with exponential backoff
  • Retry schedule: 30s, 2min, 10min, 1hr, 6hr
  • After 5 failures, the webhook is marked as failed (visible in your dashboard)
  • You can manually retry failed webhooks from the dashboard

Response Time Expectations

StateTypical Response Time
Victoria2-5 seconds
NSW3-8 seconds
Queensland2-6 seconds
South Australia3-7 seconds
Western Australia4-10 seconds
Tasmania3-8 seconds
Northern Territory5-12 seconds
ACT3-8 seconds

Note: Times may vary based on registry availability. Maximum timeout is 30 seconds before we return a timeout status.


Registry Response Structure

The registry_response object in webhook payloads contains state-specific validation results. Here's the common structure:

{
"may_engage": true,
"response": ["Current", "May Engage"],
"oho_status": "active",
"card_type": "employee_wwc",
"expiry_date": "2027-06-15"
}

Common Fields:

  • may_engage (boolean) - Whether the person is cleared to work with children
  • response (array) - Status indicators from the registry
  • oho_status (string) - Normalized status: active, inactive, expired, suspended, cancelled
  • card_type (string) - Type of WWC card (state-specific)
  • expiry_date (string) - Expiry date if available

Common Status Values

The oho_status field provides a normalized status across all states:

StatusDescriptionmay_engage
activeCurrent and valid, may work with childrentrue
inactiveNot currently active, do not engagefalse
expiredCard has expiredfalse
suspendedTemporarily suspendedfalse
cancelledPermanently cancelledfalse
pendingApplication pending (APP numbers)false
interimInterim clearance granted (some states)true

Best practice: Always check both may_engage and oho_status fields to determine if someone is cleared to work with children.


Error Responses

Age Validation Error - NSW (400)

{
"status": 400,
"message": "Validation error",
"errors": {
"birth_date": ["Age should be 18+, given - 2010-01-01"]
}
}

Age Validation Error - SA (400)

{
"status": 400,
"message": "Validation error",
"errors": {
"birth_date": ["Age should be 10+, given - 2015-01-01"]
}
}

Expired Date - QLD (400)

{
"status": 400,
"message": "Validation error",
"errors": {
"expiry": ["Date is in the past"]
}
}

Missing Required Field - QLD (400)

{
"status": 400,
"message": "Validation error",
"errors": {
"expiry": ["Missing data for required field."]
}
}

Invalid Constituent (400)

{
"status": 400,
"message": "Validation error",
"errors": {
"constituent": {
"id": ["Constituent doesn't exist in your organization"]
}
}
}

Authentication Error (401)

{
"status": 401,
"message": "You are not authorized to view this resource",
"field": "authentication"
}

Service Unavailable (503)

{
"status": 503,
"message": "The target resource is currently unavailable"
}

Best Practices

1. Use the Universal Payload Structure

For maximum compatibility and consistency, always include all applicable fields:

{
"type": "OHO_ACCRED_TYPE_CODE",
"identifier": "CARD_NUMBER",
"first_name": "First",
"middle_name": "Middle",
"surname": "Last",
"birth_date": "YYYY-MM-DD",
"alternate_name": "Previous Name",
"expiry": "YYYY-MM-DD",
"constituent": {
"id": 123
},
"correlation_id": "your-unique-id"
}

Even if some fields are optional for certain states, using the same structure everywhere:

  • Ensures your payload works across all states
  • Simplifies your codebase (one payload template)
  • Provides better tracking and data consistency
  • Future-proofs your integration

2. State-Specific Requirements

Always include for these states:

StateRequired Fields
NSWbirth_date (18+ with 3mo grace)
SAbirth_date (10+)
QLDexpiry (future date)
QLD Exemptionexpiry (future date)

3. Use Idempotency

Always provide a correlation_id for production integrations to prevent duplicate scans.

4. Handle Webhooks Reliably

  • Return 200 OK quickly (within 10 seconds)
  • Process webhook data asynchronously in your application
  • Store correlation_id with your records for matching
  • Implement webhook signature verification

Complete Integration Example

Step 1: Submit Scan

curl -X POST https://app.weareoho.com/api/scan \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "vicwwc",
"identifier": "1076131A",
"first_name": "Cameron",
"middle_name": "James",
"surname": "Schafer",
"birth_date": "1985-06-15",
"alternate_name": "Cameron Smith",
"constituent": {
"id": 113767
},
"correlation_id": "scan-cameron-20250105-001"
}'

Step 2: Receive Response

{
"correlation_id": "scan-cameron-20250105-001"
}

Step 3: Store Correlation ID

// Store the correlation_id with your internal record
await database.updateScanRequest(internalId, {
correlation_id: 'scan-cameron-20250105-001',
status: 'pending'
});

Step 4: Receive Webhook (Later)

POST https://your-domain.com/webhook/scan-results
Content-Type: application/json
X-Oho-Signature: abc123...

{
"correlation_id": "scan-cameron-20250105-001",
"type": "wwc",
"state": "vic",
"status": "completed",
"accreditation": {
"id": 5354,
"identifier": "1076131A",
"registry_response": {
"may_engage": true,
"response": ["Current", "May Engage"],
"oho_status": "active",
"card_type": "employee_wwc"
}
},
"constituent": {
"id": 113767,
"first_name": "Cameron",
"surname": "Schafer"
}
}

Step 5: Process Webhook

async function handleWebhook(req, res) {
// 1. Verify signature
const signature = req.headers['x-oho-signature'];
if (!verifyWebhook(req.body, signature, process.env.OHO_SECRET)) {
return res.status(403).send('Invalid signature');
}

// 2. Match to your records
const scanRequest = await database.findByCorrelationId(
req.body.correlation_id
);

// 3. Update your records
await database.updateScanRequest(scanRequest.id, {
status: req.body.status,
accreditation_id: req.body.accreditation?.id,
may_engage: req.body.accreditation?.registry_response?.may_engage
});

// 4. Respond quickly
res.status(200).send('OK');

// 5. Process asynchronously (after response sent)
processResult(req.body);
}

FAQ

Q: Do I need to provide all fields in the payload?

A: Required fields vary by state:

  • Always required: type, identifier, first_name, surname
  • NSW & SA: birth_date is required
  • QLD: expiry is required (must be future date)
  • All others: Optional (middle_name, alternate_name, expiry, constituent.id)

However, using a consistent payload structure for all requests simplifies your codebase and ensures compatibility.

Q: What's the difference between qldblue and qldblueex?

A: Queensland has two check types:

  • qldblue - Standard Blue Card (regular checks)
  • qldblueex - Blue Card exemption Both require the expiry field.

Q: What if I submit the same scan twice?

A: Without a custom correlation_id, each request is treated as new. Use the same correlation_id for idempotency - subsequent requests with the same ID will return the existing correlation data without creating a duplicate scan.

Note: The correlation_id may change as the item is processed, so it may not be a reliable long-term reference for tracking scans after completion. For persistent tracking, use the returned accreditation.id from the webhook response.

Q: What if the constituent doesn't exist?

A: You'll get a 400 error. Either:

  1. Create the constituent first using POST /api/constituents
  2. Or omit the constituent field to create a standalone accreditation

Q: Can I get synchronous responses?

A: The async /api/scan endpoint is recommended for production. Contact support if you need information about synchronous scanning options for testing/development.


Troubleshooting

Common Issues and Solutions

1. 401 Unauthorized Error

Problem: {"status": 401, "message": "You are not authorized to view this resource"}

Solutions:

  • ✅ Verify your API token is correct and hasn't expired
  • ✅ Check the Authorization header format: Bearer YOUR_TOKEN
  • ✅ Ensure your user account is verified (check email)
  • ✅ Confirm your organization is active and in good standing

2. 400 Validation Error - Age Check Failed

Problem (NSW): {"errors": {"birth_date": ["Age should be 18+, given - 2010-01-01"]}}

Solutions:

  • ✅ Verify the person is at least 18 years old (or will be within 3 months for NSW)
  • ✅ Check birth_date format is correct: YYYY-MM-DD
  • ✅ For SA, verify age is 10+

3. 400 Validation Error - Missing Required Field

Problem (QLD): {"errors": {"expiry": ["Missing data for required field."]}}

Solutions:

  • ✅ QLD Blue Cards require expiry field
  • ✅ Expiry must be a future date
  • ✅ Format: YYYY-MM-DD

4. 400 Constituent Not Found

Problem: {"errors": {"constituent": {"id": ["Constituent doesn't exist in your organization"]}}}

Solutions:

  • ✅ Create the constituent first: POST /api/constituents
  • ✅ Verify you're using the correct constituent ID
  • ✅ Or omit constituent field entirely for standalone accreditation

5. Webhook Not Receiving Results

Problem: Scan submitted successfully but no webhook callback received

Solutions:

  • ✅ Verify webhook URL is configured in Settings → Webhooks
  • ✅ Ensure webhook endpoint is publicly accessible via HTTPS
  • ✅ Check webhook endpoint returns 200 OK within 10 seconds
  • ✅ Verify no firewall blocking incoming requests
  • ✅ Look for failed webhooks in your dashboard

Quick Reference

Endpoint Summary

Endpoint: POST /api/scan

Content-Type: application/json

Authentication: Authorization: Bearer YOUR_TOKEN

Type Codes

StateType Codebirth_dateAgeSpecial Requirements
VictoriavicwwcOptionalNone-
NSWnswwwcRequired18+Auto-detects APP numbers
QueenslandqldblueOptionalNoneexpiry required (future)
QLD ExemptionqldblueexOptionalNoneexpiry required (future)
South AustraliasawwcRequired10+-
Western AustraliawawwcOptionalNone-
TasmaniataswwcOptionalNone-
Northern TerritoryntwwcOptionalNone-
ACTactwwcOptionalNone-

Field Requirements

Always required:

  • type - Check type code (vicwwc, nswwwc, qldblue, etc.)
  • identifier - WWC card/application number
  • first_name - First/given name
  • surname - Surname/family name

State-specific required:

  • NSW & SA: birth_date
  • QLD: expiry (must be future date)

Optional for all states:

  • middle_name
  • alternate_name (supported: VIC, QLD, WA)
  • birth_date (except NSW & SA)
  • expiry (except QLD)
  • constituent.id
  • correlation_id (recommended for idempotency)

Common HTTP Status Codes

CodeMeaningCommon Cause
200SuccessRequest queued successfully
400Bad RequestValidation error (missing/invalid field)
401UnauthorizedInvalid/missing API token
429Too Many RequestsRate limit exceeded
503Service UnavailableRegistry temporarily unavailable

Webhook Status Values

StatusDescriptionAction Required
completedValidation successfulUse result
errorValidation failedCheck error message, verify details
timeoutRegistry timeout (>30s)Retry scan
invalidInvalid credentialsVerify card number and details


Document Version

Version: 2.1 Last Updated: 2025-11-13 Endpoint: POST /api/scan (Universal with type field) Status: Production Ready