Developer guide

Australian sanctions API in C# / .NET: DFAT data in ASP.NET

Call the Australian sanctions API from an ASP.NET service. Use C# to select DFAT coverage, inspect errors, and retain evidence for review.

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

Add Australian screening to an ASP.NET service

An Australian business workflow can span local business dates and provider timestamps. Preserve the actual screening time and source version in your .NET application, and format times for users without replacing the underlying value. A date shown in the local interface should not be mistaken for the authority’s publication date.

For an invented customer correction, retain the time the input changed and the reference of the new operation. This helps reviewers distinguish a new Australian-source comparison from a delayed response to the earlier request.

Prepare the synthetic exercise

Use the synthetic .NET request to test how a screening timestamp appears in an Australian business timezone. Preserve the original instant in storage while changing only its display. A calendar date shown to a reviewer must not be relabeled as the publisher’s list-update date.

C# / .NET setup and request files
RequirementValue or action
RuntimeUse .NET 8 or later. Save the program as Program.cs and the project file shown below as Screen.csproj. HttpClient and System.Text.Json are included; no provider SDK or third-party JSON library is required.
Client fileSave the client as Program.cs
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.jsonMira Calder: invented subject; sandbox@1: synthetic records
request.json: synthetic sandbox request
{
  "subject": {
    "name": "Mira Calder",
    "entityType": "person",
    "birthDate": "1984"
  },
  "package": "sandbox@1",
  "retention": "standard"
}

Add the project configuration

Screen.csproj
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup></Project>

Implement the C# / .NET request boundary

The HttpClient adapter should save the provider result independently of the local business-date display. When a customer correction occurs near a date boundary, retain both operation references. A late response to the old operation must not overwrite the corrected customer’s new result.

C# / .NET: authenticated screening client
// .NET 8+. Backend or trusted CLI. No third-party packages.
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
try
{
    var key = Environment.GetEnvironmentVariable("SANCTIONSKIT_API_KEY") ?? "";
    var operation = Environment.GetEnvironmentVariable("SCREENING_OPERATION_ID") ?? "";
    if (key.Length == 0 || operation.Length == 0) throw new InvalidOperationException("Missing configuration");
    var raw = await File.ReadAllBytesAsync(args.Length > 0 ? args[0] : "request.json");
    if (raw.Length > 65536) throw new InvalidDataException("Oversized request");
    using var input = JsonDocument.Parse(raw);
    var body = input.RootElement;
    if (body.ValueKind != JsonValueKind.Object || !body.TryGetProperty("subject", out _) ||
        body.TryGetProperty("sources", out _) == body.TryGetProperty("package", out _))
        throw new InvalidDataException("Invalid request object");
    using var handler = new HttpClientHandler { AllowAutoRedirect = false };
    using var client = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(25) };
    using var deadline = new CancellationTokenSource(TimeSpan.FromSeconds(30));
    using var request = new HttpRequestMessage(HttpMethod.Post, "https://www.sanctionskit.com/api/v1/screenings");
    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", key);
    request.Headers.Add("Idempotency-Key", operation);
    request.Content = new StringContent(Encoding.UTF8.GetString(raw), Encoding.UTF8, "application/json");
    using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, deadline.Token);
    if (!response.IsSuccessStatusCode) throw new HttpRequestException("Incomplete HTTP response");
    await using var stream = await response.Content.ReadAsStreamAsync(deadline.Token);
    using var received = new MemoryStream();
    var buffer = new byte[8192]; int read;
    while ((read = await stream.ReadAsync(buffer.AsMemory(), deadline.Token)) != 0)
    {
        if (received.Length + read > 8 * 1024 * 1024) throw new InvalidDataException("Oversized response");
        received.Write(buffer, 0, read);
    }
    using var envelope = JsonDocument.Parse(received.ToArray());
    var root = envelope.RootElement;
    if (root.ValueKind != JsonValueKind.Object || !root.TryGetProperty("data", out var data) || data.ValueKind != JsonValueKind.Object ||
        !data.TryGetProperty("id", out var id) || id.ValueKind != JsonValueKind.String || string.IsNullOrEmpty(id.GetString()) ||
        !data.TryGetProperty("status", out var state) || state.ValueKind != JsonValueKind.String ||
        !data.TryGetProperty("matches", out var matches) || matches.ValueKind != JsonValueKind.Array)
        throw new InvalidDataException("Unexpected screening response");
    var status = state.GetString(); var count = matches.GetArrayLength();
    if ((status != "potential_match" && status != "no_match") || (status == "no_match" && count != 0) || (status == "potential_match" && count == 0))
        throw new InvalidDataException("Inconsistent screening response");
    Console.WriteLine(JsonSerializer.Serialize(new { id = id.GetString(), status, candidateCount = count }));
}
catch (Exception)
{
    Console.Error.WriteLine("Screening incomplete. Check the operation before retrying.");
    Environment.ExitCode = 1;
}

Run the client

Run the sandbox request
dotnet run --project Screen.csproj -- request.json

Confirm Australian sanctions scope before production

Select au-consolidated for the DFAT comparison and keep the source version from the completed response. A local date change is not a list update. Coverage freshness and publisher dates need their own fields rather than a timestamp inferred from when the .NET controller ran.

Production source-discovery contract
CheckRequired evidence
GET /api/v1/sourcesProduction key with sources:read; response data array
idau-consolidated
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 au-consolidated in the production request

Explicit change from the sandbox exercise
SettingProduction request
KeySeparate production credential with screenings:write
Coveragesources: ["au-consolidated"]; 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 au-consolidated selection
{
  "subject": {
    "name": "Mira Calder",
    "entityType": "person",
    "birthDate": "1984"
  },
  "sources": [
    "au-consolidated"
  ],
  "retention": "standard"
}

Interpret Australian sanctions evidence in this workflow

Write data.id and data.coverage with the original operation time. Format timestamps for the reviewer without losing their underlying value. When comparing old and corrected customer details, show which operation and version produced each result.

Australian sanctions candidate fields to retain
Fields in data.matches[]Review use
record.id and record.namesRetain the DFAT source reference with the primary name and aliases; one listed identity may have several names.
record.designationsDisplay the available designation, program, legal-reference and effective-date context.
record.birthDates, identifiers and addressesCompare 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

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
  • Display one stored instant in two timezones without changing its value.
  • Deliver an older response after a corrected-subject response and preserve both links.
  • Keep a missing publisher date unknown rather than using the controller timestamp.

Sources and references

Frequently asked questions

Which date should a .NET Australian screening history retain?

Retain the actual operation and result timestamps with their source versions. A local business-date display is useful for people, but it should not replace the underlying instant or stand in for a publisher date.

Does midnight in Australia require a different DFAT source version?

No. A timezone boundary does not establish a source update. Use the completed screening’s coverage and version evidence to describe the data checked, rather than inferring a new dataset from a local calendar date.

Where should a .NET service keep the DFAT screening reference?

Save the returned screening ID with the onboarding operation and your business reference. Keep source coverage, versions, and review state in authorized application storage. The ID lets the team reopen retained evidence without running another check just to view it.

What if an old DFAT response arrives after a C# customer correction?

Link each response to the operation that created it. Keep the corrected subject’s new result separate and preserve the earlier one as history, instead of overwriting whichever customer row happens to be current.