Outbound destinations API
Review the hosts your app calls out to, approve or flag them, manage approve and flag rules, turn destination watch on per bucket and choose which environments are production.
Destination watch keeps a list of every host each bucket’s app calls, and alerts the first time it calls a new one. See Watch for new outbound destinations for how it works in the app.
Plan: needs a plan that includes Outbound destination watch. Reading destinations, rules, watch state and environments keeps working if the plan changes. Permissions: any member, or a user or administrator API token, can read and review destinations. Rules, turning watch on or off, pruning and the production marker need an owner or admin, or an administrator API token.
Destinations are kept per bucket: the same host called from two buckets is two destinations. Hosts are canonical: lowercase, internationalized names in punycode, IPv6 addresses in brackets, no port.
The destination object
-
sid (string, required): The destination’s identifier (
dst_followed by 27 letters and digits). -
bucketSid (string, required): The bucket that calls it.
-
host (string, required): The canonical hostname.
-
domain (string, required): The registrable domain, from the ICANN section of the Public Suffix List. For an IP address, the address.
-
sharedSuffix (string | null): The shared-hosting suffix the host sits under (for example
herokuapp.com), where anyone can create hosts. An approve wildcard never covers it. -
kind (string, required):
name,ipv4,ipv6,localhost,privateormetadata. -
status (string, required):
pending(in the review queue),approved,flaggedorbaselined(approved by the import that ran when watch was turned on). -
ports (integer[], required): Non-default ports seen, up to 16.
-
portsOverflow (boolean, required): More than 16 non-default ports were seen.
-
sources (string[], required): Where the host was learned from:
sdk(outbound records) andspan(http.outspans). -
environments (object[], required): Live sightings, one per environment:
environmentSid,name,isProduction,firstSeenAtandlastSeenAt. -
historyEnvironments (object[], required): The same, for sightings found by the import that ran when watch was turned on.
-
firstSeenAt (string | null): When the host was first called (ISO 8601).
-
lastSeenAt (string | null): When it was last called.
-
firstRequestSid (string | null): The request that first called it.
-
firstTrigger (object | null): The inbound route whose handler made the first call (
inboundMethod,inboundEndpoint) when the call was seen inside a request;{"history": true}for a host found by the enablement import,{"recovered": true}for one recovered from stored traffic, andnullwhen it isn’t known (a host first seen on its own outbound record). -
correlatedEventSid (string | null): The deploy event in the hour before the first call, if any.
-
risk (object, required):
reasons: any ofip_literal,ip_encoding,metadata_endpoint,non_ascii,non_standard_portandflag_rule. A host with a reason is never approved by a rule or the import.notes: details about how the host was read. -
callsTotal (integer, required): Calls seen so far. Approximate.
-
alertState (object, required): The host’s alerts, one for production (
prod) and one for every other environment (preprod): each astate(firingorresolved) and the timeat. -
alertDeferred (boolean, required): The host’s alert is waiting for the import that runs when watch is turned on.
-
reviewedBy (string | null): Who last reviewed it.
-
reviewedAt (string | null): When.
-
reviewNote (string | null): The note left with the last review.
-
flaggedAt (string | null): When it was flagged.
-
flaggedByRuleSid (string | null): The flag rule that flagged it.
-
approvedByRuleSid (string | null): The approve rule that approved it.
-
createdAt (string | null): When it was added.
List destinations
GET https://api.apitraffic.io/v1/accounts/{accountSid}/destinations
Lists destinations, newest first. status=pending,flagged is the review queue.
Path parameters
- accountSid (path, string, required): The account identifier.
Query parameters
-
bucketSid (query, string): Only this bucket.
-
environmentSid (query, string): Only hosts this environment called.
-
status (query, string): Comma separated:
pending,approved,flagged,baselined. -
kind (query, string):
name,ipv4,ipv6,localhost,privateormetadata. -
domain (query, string): A registrable domain or shared suffix.
-
q (query, string): Part of the host.
-
risk (query, string): Only hosts with this risk reason.
-
limit (query, integer, default 100): 1 to 500.
-
cursor (query, string):
nextCursorfrom the previous page.
Response
records, a list of destination objects, hasMore and nextCursor.
curl "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinations?bucketSid=k3m9p2x&status=pending,flagged" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN"
{
"hasMore": false,
"nextCursor": null,
"records": [
{
"sid": "dst_2kM4nP6qR8sT1uV3wX5yZ7aB9cD",
"bucketSid": "k3m9p2x",
"host": "telemetry.leftpad-analytics.io",
"domain": "leftpad-analytics.io",
"sharedSuffix": null,
"kind": "name",
"status": "pending",
"ports": [],
"portsOverflow": false,
"sources": ["sdk"],
"environments": [
{ "environmentSid": "env_2pQ7rS9tU1vW3xY5zA7bC9dE1fG", "name": "production", "isProduction": true,
"firstSeenAt": "2026-10-29T10:02:11.000Z", "lastSeenAt": "2026-10-29T11:40:03.000Z" }
],
"historyEnvironments": [],
"firstSeenAt": "2026-10-29T10:02:11.000Z",
"lastSeenAt": "2026-10-29T11:40:03.000Z",
"firstRequestSid": "req_2nB5cD7eF9gH1jK3lM5nP7qR9sT",
"firstTrigger": { "inboundMethod": "POST", "inboundEndpoint": "/v1/checkout" },
"correlatedEventSid": "evt_2rT6uV8wX1yZ3aB5cD7eF9gH1jK",
"risk": { "reasons": [], "notes": [] },
"callsTotal": 184,
"alertState": { "prod": { "state": "firing", "at": "2026-10-29T10:02:26.000Z" } },
"alertDeferred": false,
"reviewedBy": null,
"reviewedAt": null,
"reviewNote": null,
"flaggedAt": null,
"flaggedByRuleSid": null,
"approvedByRuleSid": null,
"createdAt": "2026-10-29T10:02:26.000Z"
}
]
}
Get destination
GET https://api.apitraffic.io/v1/accounts/{accountSid}/destinations/{destinationSid}
Path parameters
-
accountSid (path, string, required): The account identifier.
-
destinationSid (path, string, required): The destination’s identifier.
Response
The destination object, with history: each review, rule application and automatic change (action, actor, reason, note, at), newest first, up to 100.
curl "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinations/dst_2kM4nP6qR8sT1uV3wX5yZ7aB9cD" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN"
Review destination
PATCH https://api.apitraffic.io/v1/accounts/{accountSid}/destinations/{destinationSid}
Approves, flags or reopens one destination. Approving resolves its alerts. Flagging alerts at critical severity until the host has gone 24 hours without a call.
Path parameters
-
accountSid (path, string, required): The account identifier.
-
destinationSid (path, string, required): The destination’s identifier.
Body parameters
-
status (body, string, required):
approved,flaggedorpending(reopen). -
note (body, string): Up to 500 characters. Required to flag.
Response
The updated destination object. Approving a host a flag rule flagged needs an owner or admin; anyone else gets 403.
curl -X PATCH "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinations/dst_2kM4nP6qR8sT1uV3wX5yZ7aB9cD" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "status": "flagged", "note": "Not a service we use" }'
Review destinations in bulk
POST https://api.apitraffic.io/v1/accounts/{accountSid}/destinations/review
The same review for up to 500 destinations at once. All or nothing: if one can’t be changed, none are.
Path parameters
- accountSid (path, string, required): The account identifier.
Body parameters
-
sids (body, string[], required): 1 to 500 destination identifiers.
-
status (body, string, required):
approved,flaggedorpending. -
note (body, string): Required to flag.
Response
records, the updated destination objects.
curl -X POST "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinations/review" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "sids": ["dst_2kM4nP6qR8sT1uV3wX5yZ7aB9cD"], "status": "approved" }'
Prune destinations
POST https://api.apitraffic.io/v1/accounts/{accountSid}/destinations/prune
Deletes destinations that are no longer called, to make room under the limits. Approved and baselined destinations by default. Pending ones only after 30 days without a call, and only with a note. Flagged destinations are never pruned. A pruned host that is called again is new again.
Permissions: owner or admin, or an administrator API token.
Path parameters
- accountSid (path, string, required): The account identifier.
Body parameters
-
bucketSid (body, string): Only this bucket.
-
sids (body, string[]): Only these destinations (up to 500).
-
statuses (body, string[]): Any of
approved,baselinedandpending. -
notSeenForDays (body, integer): Only destinations not called for this many days. Required unless
sidsis given, and at least 30 to prune pending destinations. -
note (body, string): Required when pruning pending destinations.
Response
deleted, how many destinations were deleted (at most 500 per call), and hasMore: when true, more match, so call again.
curl -X POST "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinations/prune" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "bucketSid": "k3m9p2x", "notSeenForDays": 90 }'
{ "deleted": 12, "hasMore": false }
The rule object
-
sid (string, required): The rule’s identifier (
dsr_followed by 27 letters and digits). -
pattern (string, required): An exact host, or
*.domainfor a domain and every name under it. -
effect (string, required):
approveorflag. Flag beats approve. -
bucketSids (string[] | null): Only these buckets;
nullmeans every bucket. -
note (string | null): Why the rule exists.
-
createdBy (string | null): Who created it.
-
createdAt (string | null): When.
-
updatedAt (string | null): When it last changed.
-
applied (integer): On create and update only: how many existing destinations the save changed.
List rules
GET https://api.apitraffic.io/v1/accounts/{accountSid}/destinationRules
Path parameters
- accountSid (path, string, required): The account identifier.
Response
records, a list of rule objects.
curl "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinationRules" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN"
Preview rule
POST https://api.apitraffic.io/v1/accounts/{accountSid}/destinationRules/preview
Shows which current destinations a rule would change, without saving it.
Path parameters
- accountSid (path, string, required): The account identifier.
Body parameters
The same as Create rule.
Response
pattern (as it would be saved), matching (destinations the pattern matches), changing (those saving it would change) and sample, up to 50 of them (sid, host, status).
curl -X POST "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinationRules/preview" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "pattern": "*.stripe.com", "effect": "approve" }'
{
"pattern": "*.stripe.com",
"matching": 3,
"changing": 2,
"sample": [
{ "sid": "dst_2kM4nP6qR8sT1uV3wX5yZ7aB9cD", "host": "api.stripe.com", "status": "pending" }
]
}
Create rule
POST https://api.apitraffic.io/v1/accounts/{accountSid}/destinationRules
Creates a rule and applies it to existing destinations straight away: a flag rule flags every matching destination; an approve rule approves matching pending ones without a risk reason.
Permissions: owner or admin, or an administrator API token.
Path parameters
- accountSid (path, string, required): The account identifier.
Body parameters
-
pattern (body, string, required): An exact host (
api.stripe.com) or*.domain(*.stripe.com). An approve wildcard over a shared-hosting suffix (*.herokuapp.com) or a public suffix (*.com) is refused with400. -
effect (body, string, required):
approveorflag. -
bucketSids (body, string[]): Only these buckets (up to 200). Leave out for every bucket.
-
note (body, string): Up to 500 characters.
Response
The rule object, with applied.
curl -X POST "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinationRules" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "pattern": "*.stripe.com", "effect": "approve", "note": "Payments provider" }'
{
"sid": "dsr_2kM4nP6qR8sT1uV3wX5yZ7aB9cE",
"pattern": "*.stripe.com",
"effect": "approve",
"bucketSids": null,
"note": "Payments provider",
"createdBy": "usr_2aB4cD6eF8gH1jK3lM5nP7qR9sT",
"createdAt": "2026-10-29T12:00:00.000Z",
"updatedAt": "2026-10-29T12:00:00.000Z",
"applied": 2
}
Update rule
PATCH https://api.apitraffic.io/v1/accounts/{accountSid}/destinationRules/{ruleSid}
Changes any of a rule’s fields. When the pattern, effect or buckets change, the rule is applied again: hosts it no longer covers lose the rule’s flag (they stay flagged, and members can review them again), and hosts it still covers keep it, along with any admin’s approval over it. Changing only the note applies nothing.
Permissions: owner or admin, or an administrator API token.
Path parameters
-
accountSid (path, string, required): The account identifier.
-
ruleSid (path, string, required): The rule’s identifier.
Body parameters
Any of pattern, effect, bucketSids and note, as in Create rule.
Response
The rule object, with applied.
curl -X PATCH "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinationRules/dsr_2kM4nP6qR8sT1uV3wX5yZ7aB9cE" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "note": "Payments and billing" }'
Delete rule
DELETE https://api.apitraffic.io/v1/accounts/{accountSid}/destinationRules/{ruleSid}
Destinations a deleted flag rule flagged stay flagged, and members can review them again.
Permissions: owner or admin, or an administrator API token.
Path parameters
-
accountSid (path, string, required): The account identifier.
-
ruleSid (path, string, required): The rule’s identifier.
Response
sid and deleted: true.
curl -X DELETE "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinationRules/dsr_2kM4nP6qR8sT1uV3wX5yZ7aB9cE" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN"
The watch object
-
bucketSid (string, required): The bucket.
-
state (string, required):
off,backfilling(importing the last 30 days of hosts),releasing(finishing the import) orwatching. -
enabled (boolean, required): Whether watch is on.
-
startedAt (string | null): When watch was last turned on.
-
backfillMode (string, required):
baselineorreview_all: what the import does with the hosts it finds. -
reconciledAt (string | null): When stored history was last checked for hosts live capture missed.
Get bucket watch
GET https://api.apitraffic.io/v1/accounts/{accountSid}/buckets/{bucketSid}/destinationWatch
Path parameters
-
accountSid (path, string, required): The account identifier.
-
bucketSid (path, string, required): The bucket identifier.
Response
The watch object.
curl "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/buckets/k3m9p2x/destinationWatch" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN"
Update bucket watch
PATCH https://api.apitraffic.io/v1/accounts/{accountSid}/buckets/{bucketSid}/destinationWatch
Turns watch on or off for a bucket. Turning it on imports the last 30 days of hosts first, so an existing app doesn’t start with every host it calls alerting as new. Alerts for new hosts wait for the import, at most 30 minutes; risky hosts alert straight away. Turning it off resolves the bucket’s destination alerts and keeps its destinations.
Permissions: owner or admin, or an administrator API token.
Path parameters
-
accountSid (path, string, required): The account identifier.
-
bucketSid (path, string, required): The bucket identifier.
Body parameters
-
enabled (body, boolean, required):
trueto turn watch on,falseto turn it off. -
backfillMode (body, string, default baseline):
baselineapproves the imported hosts (apart from risky ones);review_allputs every one in the review queue.
Response
The watch object.
curl -X PATCH "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/buckets/k3m9p2x/destinationWatch" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "enabled": true, "backfillMode": "baseline" }'
{
"bucketSid": "k3m9p2x",
"state": "backfilling",
"enabled": true,
"startedAt": "2026-10-29T12:05:00.000Z",
"backfillMode": "baseline",
"reconciledAt": null
}
List environments
GET https://api.apitraffic.io/v1/accounts/{accountSid}/destinations/environments
Lists the account’s environments and whether each counts as production for destination alerts. A host first called from production alerts at a higher severity.
Path parameters
- accountSid (path, string, required): The account identifier.
Response
records: each environmentSid, name, isProduction and source (inferred from the environment’s name, or manual).
curl "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinations/environments" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN"
Mark environment as production
PATCH https://api.apitraffic.io/v1/accounts/{accountSid}/destinations/environments/{environmentSid}
A choice made here is kept, and never replaced by inference from the environment’s name.
Permissions: owner or admin, or an administrator API token.
Path parameters
-
accountSid (path, string, required): The account identifier.
-
environmentSid (path, string, required): The environment identifier.
Body parameters
- isProduction (body, boolean, required): Whether the environment is production.
Response
The environment’s record, with source: "manual".
curl -X PATCH "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/destinations/environments/env_2pQ7rS9tU1vW3xY5zA7bC9dE1fG" \
-H "Authorization: Bearer $APITRAFFIC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "isProduction": true }'
Events
Every review, rule change, watch change and production marker is recorded in the account’s activity and sent to webhooks as a security.destination_* event. See the webhook event reference.