Docs pages

Expected outcomes

Some APIs answer a normal business case with an error status: a consent check answers 400 when the user hasn't consented, a lookup answers 404 for "no such customer yet". Counted as failures, these make the endpoint's normal noisy, and a change in how often users hit them can open an incident. Tell Theirside which answers are normal; those calls then count as successful.

Call it after your code has read the answer and decided it's a normal case:

// consent.ts
import { markExpected } from '@theirside/sdk';

export async function hasConsent(userId: string): Promise<boolean> {
  const res = await fetch(`https://api.consentco.test/v1/consent/${userId}`);
  if (res.status === 400) {
    const body = (await res.json()) as { code?: string };
    if (body.code === 'consent_required') {
      markExpected('consent_required'); // a normal answer: the user hasn't consented yet
      return false;
    }
  }
  if (!res.ok) throw new Error(`consent check failed: ${res.status}`);
  return true;
}

markExpected(reason) tags the latest outgoing call that ended in the same incoming request, if it answered with a 4xx in the last 5 seconds. It works in any Node HTTP server (Express, Fastify, NestJS). Only the reason label is sent (letters, digits and _ . : -, up to 64 characters); the SDK never reads the response itself.

In code: expecting

When you know up front, wrap the call instead. 4xx answers to the calls made inside, also from async work it starts, are tagged:

// consent-check.ts
import { expecting } from '@theirside/sdk';

export async function check(userId: string) {
  return expecting('consent_required', () => consentClient.check(userId));
}

Use expecting() outside an incoming request (queue consumers, cron jobs), and when several calls run at once in one request: markExpected() tags whichever ended last.

Why only the calls you tag

Untagged calls with the same status stay failures. So if the provider changes its contract and starts answering 400 to everything, your code doesn't recognise those answers, doesn't tag them, and you still get an alert. Only 4xx answers can be expected; a 5xx, timeout or connection error never is. Tagged calls show as their own series per reason on the endpoint page.

From the dashboard

Without a code change, mark a status as expected for a whole endpoint: from an incident ("Mark 404 as expected for POST /v1/lookup"), from the endpoint row, or in the provider's settings. Members and admins can do it, and an open incident it explains is resolved with a note. Slack alerts about 401/403, 404 or 400/409/422 have a Mark as expected button.

That is coarser: every answer with that status from that endpoint counts as fine. A safety net still opens an incident when the marked status takes over: above 80% of calls, or halfway from its normal share to every call if that is higher, with confidence, for about 10 minutes ("400 (marked expected) now 95% of calls, normally 30%").

Which to use

In code From the dashboard
Precision Only the answers your code read as normal Every answer with that status
Contract change ("400 to everything") Alerts as usual Alerts only once the status takes over
Effort A line where you handle the answer A click
Works on Node servers; expecting() anywhere Any SDK version

Start from the dashboard to quiet an endpoint today; move to markExpected where you handle the answer when you next touch that code.

Checking it

getStats().expected counts tagged calls and missed marks (a markExpected that found no 4xx to tag); with debug: true the SDK says why a mark missed.

Docs for Theirside 0.6.3. This page as Markdown.