Reference

Outbound guard

Check an invite, share or notification before your product sends it from your domain.

Server-side endpoint

POST https://nolgard.com/v1/outbound
{"secret":"sk_…","accountId":"user_42","kind":"invite","recipients":["a@example.com","b@example.com"],"text":"Join my team","ip":"198.51.100.9","userAgent":"Mozilla/5.0 …"}

{"decision":"allow","reasons":[]}

Call this before sending any user-triggered email. Keep the secret and this call on your server.

Request fields

FieldTypeNotes
secretstringRequired. Site secret.
accountIdstringRequired. The sending account, up to 256 characters.
kindstringRequired. One of invite, share, notify, message.
recipientsstring[]Required. 1 to 100 email addresses in one call.
textstringOptional. The user-controlled text that appears in the email, up to 4000 characters.
ipstringOptional. IP address of the sender.
userAgentstringOptional. User agent of the sender.

Response fields

FieldTypeNotes
decisionstringallow, review, or block.
reasonsstring[]Reason codes behind the decision. Empty on a clean allow.

review means hold the email for manual approval. block means drop it. allow means send.

Reasons and defaults

ReasonDefault
outbound_new_accountUnknown account, or one less than 24 hours old, sending to 3 or more recipients in one call (newAccountRecipients 3) or 10 or more on its first day (newAccountDaily 10)
outbound_burstMore than 50 recipients in an hour or more than 200 in a day
outbound_domain_spreadMore than 15 distinct recipient domains in an hour; freemail counts once
outbound_lureText carries a phone number of 9 or more digits, an http(s) URL or a www. host, or a billing word such as invoice, refund, renewal, subscription, payment, charged or call together with a currency amount
outbound_flagged_accountThe account carries a usage flag or a fraud label, or its last decision was block or shadow

Decision mapping: block for a flagged account, or for a lure from an unknown or new account. review for any other reason. Otherwise allow.

Errors

StatusError
400invalid-input
401invalid-secret
403read-only (demo site)
429rate-limited

Webhook

outbound.abuse
{"accountId":"user_42","kind":"invite","decision":"block","reasons":["outbound_lure"],"recipients":12}

recipients is a count rather than a list. The event fires once per account per day. See Webhooks and clawback for delivery and signing.

SDK

const result = await nolgard.outbound({
  accountId: user.id,
  kind: 'invite',
  recipients,
  text
});
if (result.decision === 'block') return;
if (result.decision === 'review') await holdForApproval(draft);

The Node SDK fails open: if the call cannot complete, it returns an allow so your email pipeline keeps running. See SDKs.

Dashboard and testing

Settings → Outbound abuse lists recent decisions and the thresholds behind them. Thresholds are owner-editable.

Test secrets are stateless: test-bot blocks, test-limit reviews, any other test secret allows. They store nothing and send no webhooks.

Data retention

text is evaluated in memory and never stored. Only counts and hashed recipient domains are kept, for 7 days.

Limits

  • Defaults are logical starting points rather than measured guarantees. Tune them for how your product sends email.
  • A real user onboarding a whole team on day one looks like a new-account burst.
  • Product emails that legitimately contain links, phone numbers or billing words can match the lure reason.
  • Recipient domain counts group freemail into one domain, so a large consumer invite list spreads less than a corporate one.
  • This endpoint decides; it does not send, queue or withhold email. Your backend owns delivery.
  • Counts and hashed recipient domains cover 7 days. Older activity is not visible to the detectors.