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

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

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

4.1.1. Version 1 (/v1)

  • Classification Only: Endpoints under /v1 will solely return the model’s classification prediction.

Response (v1):

{"class":"GRAYLISTING"}

4.1.2. Version 2 (/v2)

  • Classification with Probability: 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. 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.5. 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.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"
}

4.7. 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.7.1. Severity

  • 6 = Most severe impact on sender reputation

  • 1 = Lowest impact on sender reputation

4.8. 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";
$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.