4. HTTP API

The bounce-classifier service provides HTTP(S) endpoints for classifying bounce reasons using a machine learning model. It supports batching, caching, and can run with or without TLS.

4.1. Endpoints

  • POST /v1/bnac/single — Classify a single message, returns class only

  • POST /v2/bnac/single — Classify a single message, returns class and probability

  • POST /v1/bnac — Classify a batch or single, returns class only, uses server-side cache if enabled

  • POST /v2/bnac — Classify a batch or single, returns class and probability, uses server-side cache if enabled

  • POST /v1/backoff — Classify a batch or single for backoff actions, returns class with metadata

  • POST /normalise — Normalize a bounce message into a canonical representation

  • GET /v1/cache/stats — Get cache statistics

  • GET /v1/cache/info — Get cache configuration info

4.1.1. Version 1 (/v1)

  • BNAC classification only: BNAC endpoints under /v1 return the model’s classification prediction.

Response (v1):

{"class":"GRAYLISTING"}

4.1.2. Version 2 (/v2)

  • BNAC classification with probability: BNAC endpoints under /v2 provide both:
    • The classification prediction, and

    • An associated probability value for informational purposes.

  • Probability Usage: The provided probability is meant to supplement the classification. It’s recommended not to rely solely on this value for automated decision-making processes.

Response (v2):

{"class":"GRAYLISTING","probability":0.95663047}

4.2. HTTPS

To run the service with HTTPS you can set the environment varibales:

You can also configure the port and the host as defined in configuration:

4.3. Authentication

You can use the X-API-Key header for authentication.

The X-API-Key header is optional and can be used to restrict access to the API. If not provided, the API will still function but without authentication.

To configure the API key, look in the configuration section: API_KEY , once that is set then that key can be used in the requests:

curl -X 'POST' 'https://127.0.0.1:8443/v1/bnac/single' \
  -H 'X-API-Key: <YOUR_API_KEY_HERE>' -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"message": "smtp;451 4.7.1 <[email protected]>: Recipient address rejected: Greylisting in effect, please come back later"}'

The API key is independent of HTTPS, it can be used with HTTP as well:

curl -X 'POST' 'http://127.0.0.1:8080/v1/bnac' \
  -H 'X-API-Key: <YOUR_API_KEY_HERE>' -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"message": "smtp;451 4.7.1 <[email protected]>: Recipient address rejected: Greylisting in effect, please come back later"}'

4.4. Bounce Next Action Classification (BNAC)

4.4.1. Single Message Example

curl -X 'POST' 'http://127.0.0.1:8080/v1/bnac/single' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"message": "smtp;451 4.7.1 <[email protected]>: Recipient address rejected: Greylisting in effect, please come back later"}'

Response (v1):

{"class":"GRAYLISTING"}

Response (v2):

{"class":"GRAYLISTING","probability":0.95663047}

4.4.2. Batch Message Example

Sending multiple messages at the same time is supported and will be faster than sending them one by one.

curl -X 'POST' 'http://127.0.0.1:8080/v2/bnac' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "messages": [
      "smtp;451 4.7.1 <[email protected]>: Recipient address rejected: Greylisting in effect, please come back later",
      "smtp;450 4.0.0 <[email protected]>... User unknown..."
    ]
  }'

Response (v2):

[ {"class":"GRAYLISTING","probability":0.95663047}, {"class":"RECIPIENT_NOT_FOUND","probability":0.70459944}]

4.4.3. Results

An object with a class property is returned. The possible classifications are:

Classification

Suggested Action

Severity

Scope

BLOCK_LIST

Recipient MTA is blocking, with third-party

(e.g. Spamhaus,..) information

5

tenantid

BLOCKED

Recipient MTA is blocking,

no third-party information

3

tenantid,

grouping

DKIM

Fix DKIM

3

tenantid,

grouping

DMARC

Fix DMARC

3

tenantid,

grouping

DNS_PTR

Fix reverse DNS

3

tenantid,

grouping

DOMAIN_REPUTATION

Slow down from this sending domain

4

tenantid,

grouping

GRAYLISTING

Slow down to this recipient domain,

you are at risk of being blocked

3

tenantid,

grouping

IP_REPUTATION

Slow down from this sending IP

4

localip,

grouping

MESSAGE_CONTENT

Suspend campaign and review what is sent

3

jobid

MX_ERROR

Verify your DNS resolution of this recipient

domain

3

remotemx

PROTOCOL_ERROR

Verify the MTA configuration and protocols

1

grouping

RATE_LIMIT

Slow down to this recipient domain

3

grouping

RECIPIENT_ERROR

Slow down, possible poor list quality,

reduce frequency to this address

2

jobid,

grouping

RECIPIENT_NOT_FOUND

Remove the address

1

recipient address

SPF

Fix SPF

3

tenantid,

grouping

TEMPORARY_ERROR

Slow down sending to this recipient domain

1

tenantid,

grouping

TLS

Check your TLS negotiation with this

recipient domain

3

tenantid,

grouping

VIRUS

Suspend campaign and review what is sent

6

jobid

4.4.4. Severity

  • 6 = Most severe impact on sender reputation

  • 1 = Lowest impact on sender reputation

4.4.5. BNAC Example HSL script

This example script can be run from the terminal directly with hsh. It is equivalent to the curl example above, passing in a message and receiving a response.

$guru = "http://127.0.0.1:8000/v1/bnac/single";
$options = ["headers" => ["Content-Type: application/json", "Accept: application/json"], "extended_result" => true];
$data = "451 4.7.1 <[email protected]>: Recipient address rejected: Greylisting in effect, please come back later";
$payload = json_encode(["message" => $data]);
$res = http($guru, $options, [], $payload);
if ($res["content"]) {
    $content = json_decode($res["content"]);
    $class = $content["class"];
    echo $class;
}

For best performance in calls from script hooks, use the http-background plugin instead of the foreground http function.

4.5. Backoff Action Classification

The /v1/backoff endpoint is used by the sending MTA to determine the action it should take in response to an SMTP bounce message returned by the receiving MTA. While identifying the specific cause of a failure is the responsibility of the BNAC model, the Backoff model is essential for implementing automated backoff logic and handling all failure types effectively.

Optional Query Parameters

Parameter

Type

Description

Default

bypass_cache

boolean

When true, skip reading/writing the cache

false

return_probability

boolean

When true, include probability for each class instead of class-only responses

false

4.5.1. Example request (default behaviour)

curl -X 'POST' 'http://127.0.0.1:8080/v1/backoff' \
  -H 'Content-Type: application/json' \
  -d '{
    "message": "smtp;451 4.7.1 <[email protected]>: Recipient address rejected: Greylisting in effect, please come back later"
  }' -w "\n"

Returns:

[{"class":"GRAYLISTING","fields":[],"actions":[]}]

4.5.2. Example request (single message, returning probability)

curl -X 'POST' 'http://127.0.0.1:8080/v1/backoff?return_probability=true' \
  -H 'Content-Type: application/json' \
  -d '{
    "message": "smtp;451 4.7.1 <[email protected]>: Recipient address rejected: Greylisting in effect, please come back later"
  }' -w "\n"

Returns:

[{"class":"GRAYLISTING","probability":0.9574445,"fields":[],"actions":[]}]

4.5.3. Example request (batch, class-only response)

curl -X 'POST' 'http://127.0.0.1:8080/v1/backoff?bypass_cache=true' \
  -H 'Content-Type: application/json' \
  -d '{
    "messages": [
      "smtp;451 4.7.1 <[email protected]>: Recipient address rejected: Greylisting in effect, please come back later",
      "smtp;450 4.0.0 <[email protected]>... User unknown..."
    ]
  }' -w "\n"

Returns:

[{"class":"GRAYLISTING","fields":[],"actions":[]},{"class":"RECIPIENT_ERROR","fields":[],"actions":[]}]

4.5.4. Backoff Results

A response object always includes class, fields and actions. When return_probability=true is used, it also includes probability. The possible classifications are:

Classification

AUTHENTICATION_ERROR

CONCURRENCY_LIMIT

CONNECTION_FAILURE

CONTENT_REJECTED_OTHER

CONTENT_REJECTED_SPAM

CONTENT_REJECTED_VIRUS

GENERIC_BLOCK

GRAYLISTING

INFRASTRUCTURE_BLOCK

INFRASTRUCTURE_ERROR

MAILBOX_FULL

POLICY_VIOLATION_SPF_DMARC__DKIM_FAIL

POLICY_VIOLATION_SPF_DMARC__SPF_OR_DMARC_FAIL

PROTOCOL_ERROR

RATE_LIMIT__DOMAIN_RATE_LIMIT

RATE_LIMIT__GENERAL

RATE_LIMIT__IP_RATE_LIMIT

RATE_LIMIT__RECIPIENT_LIMIT

RATE_LIMIT__SERVER_BUSY

RATE_LIMIT__URL_DOMAIN

RECIPIENT_ERROR

SENDER_REPUTATION__DOMAIN

SENDER_REPUTATION__SENDER_ADDRESS

TEMPORARY_SYSTEM_FAILURE

4.6. Cache

4.6.1. Cache Endpoints

curl -X 'GET' 'http://127.0.0.1:8080/v1/cache/stats' -H 'accept: application/json'
curl -X 'GET' 'http://127.0.0.1:8080/v1/cache/info'  -H 'accept: application/json'

4.6.1.1. Cache statistics

curl -X 'GET' 'http://127.0.0.1:8080/v1/cache/stats' -H 'accept: application/json'

Returns:

{
    "cache_enabled": true,
    "stats_enabled": false,
    "timer_enabled": false,
    "hit_requests": 0,
    "miss_requests": 0,
    "size_in_bytes": 12288,
    "number_of_elements": 0,
    "avg_get_time_ms": 0,
    "avg_set_time_ms": 0
}

4.6.1.2. Cache info

Cache info endpoint returns the current cache configuration, including whether it is enabled (see HALON_BNAC_CACHE), the folder where it is stored (see HALON_BNAC_CACHE_FOLDER), and the maximum size in bytes (see HALON_BNAC_CACHE_SIZE).

{
    "cache_enabled": true,
    "folder": "/var/lib/halon/bounce-classifier",
    "max_size": "104857600"
}