Developer guide
Australian sanctions API in Ruby: DFAT screening jobs
Run Australian sanctions API checks in a Ruby background job. Use DFAT source IDs and save alias evidence with the customer’s review.

On this page
Run Australian screening in a Ruby job
A customer renewal or corrected legal identity can create a new screening operation under your policy. Persist the event reason, subject and selected Australian coverage before enqueuing work. The worker should load that record instead of reconstructing a potentially changed customer from a display name.
When a job retries after a transport failure, preserve the original operation identity. A customer correction is a separate event with a new payload and key. Keeping these cases distinct makes it possible to explain whether a later result reflects recovery or a genuinely new comparison.
Prepare the synthetic exercise
Give an invented customer renewal and a corrected legal name different saved event references. The Ruby worker should load the event’s stored subject, not reconstruct it from the latest display name. This tests whether later corrections can accidentally alter an earlier queued operation.
| Requirement | Value or action |
|---|---|
| Runtime | Use Ruby 3.1 or later with its standard JSON, Net::HTTP, URI, and OpenSSL libraries. The script is intended for a backend or trusted CLI and needs no provider SDK. |
| Client file | Save the client as screen.rb |
| Screening endpoint | POST /api/v1/screenings |
| SANCTIONSKIT_API_KEY | Sandbox key; screenings:write and results:read scopes |
| SCREENING_OPERATION_ID | Persist one operation ID; reuse only with the identical request body |
| request.json | Mira Calder: invented subject; sandbox@1: synthetic records |
{
"subject": {
"name": "Mira Calder",
"entityType": "person",
"birthDate": "1984"
},
"package": "sandbox@1",
"retention": "standard"
}Implement the Ruby request boundary
Use Net::HTTP within a job that owns the original operation key and body. A retry after a network failure should recover that event. A renewal or corrected identity is a different event and therefore requires a new operation, even if the same Ruby job class handles both.
# Ruby 3.1+. Standard library only. Backend or trusted CLI.
require 'json'
require 'net/http'
require 'uri'
require 'openssl'
begin
key = ENV.fetch('SANCTIONSKIT_API_KEY')
operation = ENV.fetch('SCREENING_OPERATION_ID')
raise 'Operation ID must not be empty.' if operation.empty?
raw = File.binread(ARGV[0] || 'request.json')
raise 'Request file exceeds 64 KiB.' if raw.bytesize > 65_536
body = JSON.parse(raw)
unless body.is_a?(Hash) && body['subject'] && (body.key?('sources') ^ body.key?('package'))
raise 'Supply a subject and exactly one of sources or package.'
end
uri = URI('https://www.sanctionskit.com/api/v1/screenings')
request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Bearer #{key}"
request['Content-Type'] = 'application/json'
request['Idempotency-Key'] = operation
request.body = JSON.generate(body)
payload = +''
status = 0
Net::HTTP.start(uri.host, uri.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_PEER,
open_timeout: 10, read_timeout: 25, write_timeout: 25) do |http|
http.max_retries = 0
http.request(request) do |response|
status = response.code.to_i
response.read_body do |chunk|
raise 'Response size limit exceeded.' if payload.bytesize + chunk.bytesize > 8 * 1024 * 1024
payload << chunk
end
end
end
# Net::HTTP does not automatically follow redirects.
envelope = JSON.parse(payload)
raise "Screening incomplete: HTTP #{status}." unless (200...300).cover?(status)
data = envelope.is_a?(Hash) ? envelope['data'] : nil
unless data.is_a?(Hash) && data['id'].is_a?(String) && !data['id'].empty? &&
%w[potential_match no_match].include?(data['status']) && data['matches'].is_a?(Array)
raise 'Incomplete response: unexpected screening shape.'
end
count = data['matches'].length
if (data['status'] == 'no_match' && count != 0) || (data['status'] == 'potential_match' && count == 0)
raise 'Incomplete response: inconsistent screening shape.'
end
puts JSON.generate(id: data['id'], status: data['status'], candidateCount: count)
rescue StandardError => error
warn "Screening did not complete: #{error.class}. Check the operation before retrying."
exit 1
endRun the client
ruby screen.rb request.jsonConfirm Australian sanctions scope before production
Choose au-consolidated for the DFAT list and retain that selection with each renewal event. An unavailable or stale Australian source must leave the event incomplete; it cannot be replaced with a no-match outcome just to clear the queue.
| Check | Required evidence |
|---|---|
| GET /api/v1/sources | Production key with sources:read; response data array |
| id | au-consolidated |
| availability / fresh | available / true |
| capabilities | Contains the requested subject.entityType |
| currentVersion | Active version; retrieved_at and last_checked_at are not publication dates |
| lastImport | May describe an import that is not the active version |
| Missing or ineligible source | Inspect disabledReason; required coverage stays incomplete |
| Displayed client | Add these discovery checks before its production call |
curl --fail-with-body --max-time 25 --header "Authorization: Bearer $SANCTIONSKIT_API_KEY" "https://www.sanctionskit.com/api/v1/sources"Select au-consolidated in the production request
| Setting | Production request |
|---|---|
| Key | Separate production credential with screenings:write |
| Coverage | sources: ["au-consolidated"]; omit package |
| Operation ID | New ID for the changed body and environment |
| Usage | Production access and screening allowance apply |
| Subject | Only lawfully held, known identifying facts; no invented date precision |
{
"subject": {
"name": "Mira Calder",
"entityType": "person",
"birthDate": "1984"
},
"sources": [
"au-consolidated"
],
"retention": "standard"
}Interpret Australian sanctions evidence in this workflow
Keep data.id, data.coverage and the renewal reason together. Reviewers should be able to tell whether a later screening reflects new customer details or recovery of a failed request. Preserve the original aliases and source record references with each completed result.
| Fields in data.matches[] | Review use |
|---|---|
| record.id and record.names | Retain the DFAT source reference with the primary name and aliases; one listed identity may have several names. |
| record.designations | Display the available designation, program, legal-reference and effective-date context. |
| record.birthDates, identifiers and addresses | Compare the known identity details and retain uncertain dates at the precision supplied. |
- 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
| Condition | Next action |
|---|---|
| 401 / 403 | Correct credentials or scopes before retrying |
| coverage_unavailable / stale_coverage | Keep required coverage incomplete; no silent source substitution |
| Timeout after submission | Recover with the original Idempotency-Key and identical body |
| 409 | Investigate an operation-key conflict |
| 429 / 503 | Follow the specific error and Retry-After; an allowance cap may require a plan or usage change |
Contract and safe diagnostic references
| Reference | Use |
|---|---|
| error.code / error.requestId | Safe recovery diagnostics; never log the submitted subject, key or full candidate response |
| potential_match / no_match | Completed comparison outcomes; neither is an automatic business approval |
- Change the customer after enqueueing and confirm the original operation body stays unchanged.
- Give a corrected identity a new operation key.
- Mock stale_coverage and keep the renewal event incomplete.
Sources and references
Authority and technical sources
SanctionsKit documentation
Frequently asked questions
Should a Ruby DFAT job load the latest customer name every time it retries?
No. Load the subject saved with that operation. Reconstructing it from a changed customer record can turn a retry into a different request while reusing the old key, making recovery ambiguous.
How does a Ruby service distinguish Australian renewal checks from retries?
Persist the event reason and operation identity. A renewal or corrected subject creates new work; a transport retry recovers the original request. The same worker class can handle both without conflating them.
What should a Ruby job do when the Australian source is stale?
Leave the screening incomplete and check the source freshness error. Do not turn stale_coverage into no_match. Keep the original operation and required source so it can be recovered when freshness is restored.
Can a stale DFAT source be treated as a completed Ruby job?
You may record a durable failure state, but the screening itself remains incomplete. Do not label it no_match or advance the customer merely because the queue framework finished executing the job.