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
| State | Verification Speed | Monitoring Frequency | Employer Linkage | Renewal Auto-Updates |
|---|---|---|---|---|
| VIC | <10 seconds | Weekly | No (employee responsibility) | Yes |
| NSW | Hours | Annual + direct OCG alerts | Yes (automatic) | Yes |
| QLD | <10 seconds | Weekly | Yes (manual) | No |
| SA | <10 minutes | Weekly | Yes (automatic) | Yes |
| WA | <10 seconds | Weekly | No | Yes |
| TAS | <10 minutes | Weekly | No | Yes |
| NT | <10 minutes | Weekly | No | Yes |
| ACT | Monthly (manual) | Monthly | No | Yes |
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:
- Active organization account - Your organization must be active and in good standing
- Verified user status - Your API user must have completed email verification
- 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
| Field | Type | Description | Required States | Optional States |
|---|---|---|---|---|
type | string | Check type code (see table below) | All states | - |
identifier | string | WWC card or application number | All states | - |
first_name | string | First/given name | All states | - |
middle_name | string | Middle name(s) | - | All states |
surname | string | Surname/family name | All states | - |
birth_date | string (YYYY-MM-DD) | Date of birth | NSW, SA | VIC, QLD, WA, TAS, NT, ACT |
expiry | string (YYYY-MM-DD) | Expiry date (must be future) | QLD (both types) | VIC, WA (optional) |
alternate_name | string | Maiden/previous name | - | VIC, QLD, WA |
constituent.id | integer | Link to existing constituent | - | All states (recommended) |
Supported Check Types
Each state has a specific type code to use in the payload:
| State/Territory | Type Code | birth_date | Age Check | Special Notes |
|---|---|---|---|---|
| Victoria | vicwwc | Optional | None | Supports alternate_name |
| New South Wales | nswwwc | Required | 18+ (3mo grace) | Auto-detects APP numbers |
| Queensland | qldblue | Optional | None | Requires expiry (future date) |
| Queensland Exemption | qldblueex | Optional | None | Requires expiry for exemptions |
| South Australia | sawwc | Required | 10+ | - |
| Western Australia | wawwc | Optional | None | Supports alternate_name, expiry |
| Tasmania | taswwc | Optional | None | - |
| Northern Territory | ntwwc | Optional | None | - |
| ACT | actwwc | Optional | None | - |
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:
- Let the API generate one (recommended for most cases) - returned in the response
- 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_idmultiple times, only the first request is processed - Subsequent requests with the same
correlation_idreturn 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:
- Match webhook responses to your original requests
- Debug issues by providing the ID to support
- Query scan status via the status endpoint (if available)
- 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), usetype: "qldblue" - Exemption Card: May include prefix
EX(e.g.,EX123456), usetype: "qldblueex" - Example:
123456/1(standard),EX123456(exemption)
South Australia (type: "sawwc")
- Format: 8 digits
- Example:
12345678
Western Australia (type: "wawwc")
- Format:
WWCprefix + 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
expiryfield (must be a future date) - Use
type: "qldblue"for regular cards ortype: "qldblueex"for exemptions birth_dateis 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_dateand validates age is 10+ - SA WWCC requires a middle name to be included in the
full_namefield (provided asfirst_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:
Scenario 1: Link to Existing Constituent (Recommended)
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,emailif those fields are null - ❌ Returns
400error 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:
- Create the constituent first using
POST /api/constituents - Then submit the scan with the returned constituent ID
- Or omit
constituententirely 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:
- Log in to your Oho account
- Navigate to Settings → Webhooks → Scan Results
- Enter your webhook endpoint URL (must be HTTPS)
- Save and verify the endpoint
Webhook endpoint requirements:
- Must be publicly accessible via HTTPS (HTTP not supported for security)
- Should respond with
200 OKwithin 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 requestcontent.current- Contains the complete accreditation detailscontent.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:
| Status | Description |
|---|---|
active | Valid and current clearance |
inactive | Clearance expired or revoked |
suspended | Clearance temporarily suspended |
cancelled | Clearance cancelled |
The content.current.status_flags object provides detailed state information:
| Flag | Description |
|---|---|
current | Whether the clearance is currently valid |
may_engage | Whether the person is authorized to work with children |
expired | Whether the clearance has expired |
expiring | Whether 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:
- All webhooks include an
X-Hub-Signatureheader with HMAC-SHA1 signature in formatsha1=<hex> - Use your webhook secret (not API key) to verify the signature matches the payload
- 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
| State | Typical Response Time |
|---|---|
| Victoria | 2-5 seconds |
| NSW | 3-8 seconds |
| Queensland | 2-6 seconds |
| South Australia | 3-7 seconds |
| Western Australia | 4-10 seconds |
| Tasmania | 3-8 seconds |
| Northern Territory | 5-12 seconds |
| ACT | 3-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 childrenresponse(array) - Status indicators from the registryoho_status(string) - Normalized status:active,inactive,expired,suspended,cancelledcard_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:
| Status | Description | may_engage |
|---|---|---|
active | Current and valid, may work with children | true |
inactive | Not currently active, do not engage | false |
expired | Card has expired | false |
suspended | Temporarily suspended | false |
cancelled | Permanently cancelled | false |
pending | Application pending (APP numbers) | false |
interim | Interim 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:
| State | Required Fields |
|---|---|
| NSW | birth_date (18+ with 3mo grace) |
| SA | birth_date (10+) |
| QLD | expiry (future date) |
| QLD Exemption | expiry (future date) |
3. Use Idempotency
Always provide a correlation_id for production integrations to prevent duplicate scans.
4. Handle Webhooks Reliably
- Return
200 OKquickly (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_dateis required - QLD:
expiryis 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 theexpiryfield.
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:
- Create the constituent first using
POST /api/constituents - Or omit the
constituentfield 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
Authorizationheader 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
expiryfield - ✅ 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
constituentfield 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 OKwithin 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
| State | Type Code | birth_date | Age | Special Requirements |
|---|---|---|---|---|
| Victoria | vicwwc | Optional | None | - |
| NSW | nswwwc | Required | 18+ | Auto-detects APP numbers |
| Queensland | qldblue | Optional | None | expiry required (future) |
| QLD Exemption | qldblueex | Optional | None | expiry required (future) |
| South Australia | sawwc | Required | 10+ | - |
| Western Australia | wawwc | Optional | None | - |
| Tasmania | taswwc | Optional | None | - |
| Northern Territory | ntwwc | Optional | None | - |
| ACT | actwwc | Optional | None | - |
Field Requirements
Always required:
type- Check type code (vicwwc, nswwwc, qldblue, etc.)identifier- WWC card/application numberfirst_name- First/given namesurname- Surname/family name
State-specific required:
- NSW & SA:
birth_date - QLD:
expiry(must be future date)
Optional for all states:
middle_namealternate_name(supported: VIC, QLD, WA)birth_date(except NSW & SA)expiry(except QLD)constituent.idcorrelation_id(recommended for idempotency)
Common HTTP Status Codes
| Code | Meaning | Common Cause |
|---|---|---|
| 200 | Success | Request queued successfully |
| 400 | Bad Request | Validation error (missing/invalid field) |
| 401 | Unauthorized | Invalid/missing API token |
| 429 | Too Many Requests | Rate limit exceeded |
| 503 | Service Unavailable | Registry temporarily unavailable |
Webhook Status Values
| Status | Description | Action Required |
|---|---|---|
completed | Validation successful | Use result |
error | Validation failed | Check error message, verify details |
timeout | Registry timeout (>30s) | Retry scan |
invalid | Invalid credentials | Verify card number and details |
Related Documentation
- WWCC Capability Reference - Detailed state-by-state capability scenarios
- WWCC Check Type Reference - Complete API specification and field requirements
- API Documentation - Auto-generated API reference
Document Version
Version: 2.1
Last Updated: 2025-11-13
Endpoint: POST /api/scan (Universal with type field)
Status: Production Ready