Email Broadcasting

Overview

The Infomaxim Email Broadcasting API lets you manage customer subscriptions to publications. Publications are defined in aurora_publications and customers are stored in aurora_customers. Subscription links between customers and publications are maintained in aurora_related.

Key Features

  • Public Subscribe: Any visitor can subscribe using their email. Optional first and last names can also be provided and are stored on new customer records.
  • Customer Unsubscribe: Authenticated customers can remove their own subscription at any time.
  • Admin Subscriber List: Administrators can retrieve a full list of subscribers for any publication.

Database Tables

  • aurora_customers

    Stores customer accounts. A minimal record is created automatically during subscription if the customer does not already exist. The email is always stored, and optional firstname / lastname values are stored when supplied.

  • aurora_publications

    Defines the publications that customers can subscribe to. Each publication has a unique numeric ID used in the subscription endpoints.

  • aurora_related

    Stores the subscription links. Each row relates a customer (parent_table = 'aurora_customers') to a publication (name = 'aurora_publications') with reltype = 'subscribed'.

Base URL

POST  /broadcast/subscribe
POST  /broadcast/unsubscribe
GET   /broadcast/subscribers/:publicationId

POST/broadcast/subscribe

Subscribes a customer to a publication. This endpoint is not secured — no authentication token is required, making it suitable for public-facing sign-up forms.

If no customer record exists for the supplied email address, one is created automatically. Duplicate subscriptions are silently ignored.

Authentication

Application identity is established via the site-id header (required). No customer token is needed.

site-id: YOUR_APP_ID

Request Body

{
  "email": "subscriber@example.com",
  "publicationId": 42,
  "firstName": "Alice",
  "lastName": "Smith"
}

Parameters

  • email string required

    Email address of the subscriber. Used to look up or create an aurora_customers record.

  • publicationId integer required

    Numeric ID of the publication in aurora_publications.

  • firstName string optional

    Subscriber first name. If supplied for a newly created customer, this is stored in aurora_customers.firstname.

  • lastName string optional

    Subscriber last name. If supplied for a newly created customer, this is stored in aurora_customers.lastname.

Success Response (200 OK) — new subscription

{
  "status": "Success",
  "message": "Subscribed successfully",
  "alreadySubscribed": false
}

Success Response (200 OK) — already subscribed

{
  "status": "Success",
  "message": "Already subscribed",
  "alreadySubscribed": true
}

Error Response — missing parameters (400)

{
  "status": "Failed",
  "message": "email is required"
}

Error Response — unauthorized app (401)

{
  "status": "Error",
  "message": "Unauthorized"
}

Example (JavaScript)

const response = await fetch('/broadcast/subscribe', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'site-id': '42'
  },
  body: JSON.stringify({
    email: 'subscriber@example.com',
    publicationId: 7,
    firstName: 'Alice',
    lastName: 'Smith'
  })
});
const data = await response.json();
console.log(data.status); // "Success"

POST/broadcast/unsubscribe

Removes a customer's subscription to a publication. This endpoint is secured by Customer auth — the caller must supply the encrypted customer ID that was returned by the POST /customers/login endpoint.

Authentication

Pass the encrypted _id received on login as customerId in the request body.

site-id: YOUR_APP_ID

Request Body

{
  "customerId": "ENCRYPTED_CUSTOMER_ID",
  "publicationId": 42
}

Parameters

  • customerId string required

    Encrypted customer ID. This is the _id value returned by POST /customers/login. The server decrypts this value to identify the customer.

  • publicationId integer required

    Numeric ID of the publication to unsubscribe from.

Success Response (200 OK) — subscription removed

{
  "status": "Success",
  "message": "Unsubscribed successfully",
  "removed": true
}

Success Response (200 OK) — no active subscription

{
  "status": "Success",
  "message": "No active subscription found",
  "removed": false
}

Error Response — invalid credentials (401)

{
  "status": "Failed",
  "message": "Invalid customer credentials"
}

Example (JavaScript)

// After login, store the _id returned from POST /customers/login
const customerId = loginResponse.data._id;

const response = await fetch('/broadcast/unsubscribe', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'site-id': '42'
  },
  body: JSON.stringify({
    customerId: customerId,
    publicationId: 7
  })
});
const data = await response.json();
console.log(data.message); // "Unsubscribed successfully"

GET/broadcast/subscribers/:publicationId

Returns all subscribers for the specified publication. This endpoint is secured by Admin auth — a valid admin JWT token is required.

Authentication

Requires a valid admin JWT access token obtained from POST /auth/login.

Authorization: Bearer YOUR_ADMIN_JWT_TOKEN
site-id: YOUR_APP_ID

URL Parameter

  • publicationId integer required

    Numeric ID of the publication whose subscribers should be returned.

Success Response (200 OK)

{
  "status": "Success",
  "publicationId": 42,
  "count": 2,
  "data": [
    {
      "customerId": 101,
      "email": "alice@example.com",
      "firstname": "Alice",
      "lastname": "Smith",
      "displayname": "Alice Smith",
      "subscribedDate": "2025-09-01T10:23:00.000Z"
    },
    {
      "customerId": 204,
      "email": "bob@example.com",
      "firstname": "Bob",
      "lastname": "Jones",
      "displayname": null,
      "subscribedDate": "2025-09-15T08:00:00.000Z"
    }
  ]
}

Error Response — unauthorized (401 / 403)

{
  "error": "User should have admin access to use this endpoint"
}

Example (JavaScript)

// adminToken obtained from POST /auth/login
const response = await fetch('/broadcast/subscribers/42', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer ' + adminToken,
    'site-id': '42'
  }
});
const data = await response.json();
console.log(`${data.count} subscribers found`);
data.data.forEach(s => console.log(s.email, s.subscribedDate));

Security Considerations

Endpoint Access Levels

Access level summary
Endpoint Auth Required
POST /broadcast/subscribe None (public) — site-id header only
POST /broadcast/unsubscribe Customer auth — encrypted customerId in body
GET /broadcast/subscribers/:id Admin JWT token + admin role

Customer Identity Protection

Customer IDs are never transmitted in plain text. The customerId field in the unsubscribe request must be the AES-encrypted value returned by the login endpoint. The server decrypts this value server-side; a tampered or plain-text value will be rejected with a 401 response.

Duplicate Subscription Prevention

The subscribe endpoint checks for an existing active subscription before inserting a new record. Submitting the same email and publication ID twice is safe and will return alreadySubscribed: true without creating a duplicate row in aurora_related.

SQL Injection Protection

All database operations use parameterized queries with typed parameters (sql.Int, sql.VarChar). No user-supplied input is concatenated directly into SQL strings.

Application Scoping

Subscriber queries are scoped to the requesting application via aurora_data.shop_id, ensuring that data from one application is never exposed to another.