TerraGuard

Sending CAP Data

A step-by-step integration guide for external organizations pushing Common Alerting Protocol (CAP v1.2) alerts into TerraGuard — request format, message requirements, responses, retries, and FAQ.

Who this guide is for

This guide is for an external organization that TerraGuard has onboarded as a CAP source and issued an API key to. It covers everything you need to send alert data into TerraGuard over the CAP webhook: the request format, what your CAP message must contain, how to read the responses, and how to handle updates, retries, and errors.

If you want the bigger picture — the architecture, the admin side, and how your data is transformed once it arrives — see CAP Webhook Ingestion.

The endpoint is the same for everyone; your key is unique to you.

  • Ingest endpoint: https://api.terraguard.ai/v1/ingest/webhook
  • API key: issued to your organization at onboarding and shown once — store it securely; it cannot be retrieved again (only revoked and reissued).

At a glance

Method / URLPOST https://api.terraguard.ai/v1/ingest/webhook
AuthX-API-Key: <your-api-key> header
BodyA single CAP v1.2 message, as XML or JSON
Content-Typeapplication/xml or application/json (format is also auto-detected)
Max size8 MiB per request
Success202 Accepted
StandardCAP v1.2 (OASIS)

Step 1 — Authenticate

Send your API key in the X-API-Key header on every request. The key identifies your organization, so every alert you send is attributed to you.

POST /v1/ingest/webhook HTTP/1.1
Host: api.terraguard.ai
X-API-Key: 9NcjcLHg...your-key...
Content-Type: application/xml

Treat the key like a password. Don't embed it in client-side code or commit it to a repository. If it's exposed, contact TerraGuard to revoke and reissue it — your old key stops working immediately.

Step 2 — Build a valid CAP message

TerraGuard validates each message against the CAP v1.2 envelope. At minimum your alert must include:

ElementRequiredNotes
identifierUnique ID for the alert. Reuse the same value to update an existing alert (see Updates).
senderYour sender identifier.
sentISO-8601 timestamp (e.g. 2026-05-24T07:43:37+02:00).
statusActual, Exercise, System, Test, or Draft.
msgTypeAlert, Update, Cancel, Ack, or Error.
scopePublic, Restricted, or Private.
info✅ (≥1)At least one info block (see below).

Each <info> block should carry:

ElementUsed by TerraGuard for
eventThe event type (mapped to TerraGuard's categories via your source configuration).
severityThe alert level (Extreme/Severe/Moderate/Minor).
urgency, certaintyStandard CAP qualifiers (recommended).
headline / descriptionTitle and detail shown in TerraGuard.
languageMultilingual alerts are supported — send one <info> per language. TerraGuard selects the one matching your configured language.
area (polygon / circle / geocode)The location (see Location).

Test messages. Set status to Test (or Exercise) for messages that should not be treated as real events while you're integrating. Coordinate with TerraGuard on how test traffic is handled for your source.

Step 3 — Send it

curl -X POST "https://api.terraguard.ai/v1/ingest/webhook" \
  -H "X-API-Key: <your-api-key>" \
  -H "Content-Type: application/xml" \
  --data-binary @alert.xml

A successful request returns 202 Accepted:

{
  "success": true,
  "message": "accepted and processed (processed)",
  "payload": {
    "raw_record_id": "460da342-1cd3-48f0-8241-97bb17396169",
    "source_slug": "your-org",
    "status": "accepted",
    "alert_identifier": "2.49.0.0.203.0.CZ.260401074337.XOCZ50_OKPR_000107",
    "msg_type": "Update"
  }
}

Keep the raw_record_id from the response — it uniquely identifies what TerraGuard received and is the fastest reference if you ever need TerraGuard to investigate a specific submission.

Responses & how to handle them

HTTPstatusMeaningWhat you should do
202acceptedReceived and processed into an event.Done.
202UNPROFILEDReceived and safely stored, but your source isn't fully configured yet (or the message couldn't be placed). No data is lost — it's processed once configuration is complete.Nothing required. Reach out if you expected it to be accepted.
401Missing / invalid / revoked key, or your source is deactivated.Check the X-API-Key header. If it should be valid, contact TerraGuard. Do not retry blindly.
413Body exceeds 8 MiB.Reduce the payload (e.g. split very large multi-area alerts).
422The body was received but failed CAP validation.Fix the message (see the error text), then resend.
503Temporary server-side failure (persistence/processing).Retry with backoff.

Retry guidance

  • Retry on 503 and on network errors/timeouts, using exponential backoff (e.g. 1s, 2s, 4s, …) with a cap and jitter.
  • Do not retry 401, 413, or 422 — these won't succeed until you change something (the key, the size, or the message).
  • Retries are safe: TerraGuard de-duplicates, so re-sending the same message will not create a duplicate event (see below).

Updates, cancellations & deduplication

  • Same event, new information: send a new message with the same identifier and msgType = Update. TerraGuard treats it as the same event and updates it in place.
  • Withdraw an alert: send msgType = Cancel referencing the original identifier.
  • Exact duplicates: if you resend a byte-for-byte identical message (e.g. a retry), it is detected by content hash and does not create a duplicate.

How location is determined

TerraGuard derives a location from your <area> in this order:

  1. Polygon — the centroid of the polygon, if present.
  2. Circle — the circle's centre, if present.
  3. Geocodes only — if your alert carries only area codes (e.g. region/municipality codes) with no coordinates, the event is placed at the country/region centroid.

If precise placement matters for your alerts, include polygon or circle geometry in the <area>. Coordinate-free, geocode-only alerts are placed at a country/region centroid.

Full example message

A minimal, valid CAP v1.2 alert in XML:

<?xml version="1.0" encoding="UTF-8"?>
<alert xmlns="urn:oasis:names:tc:emergency:cap:1.2">
  <identifier>ORG-2026-05-24-000123</identifier>
  <sender>alerts@your-org.example</sender>
  <sent>2026-05-24T07:43:37+02:00</sent>
  <status>Actual</status>
  <msgType>Alert</msgType>
  <scope>Public</scope>
  <info>
    <language>en</language>
    <category>Met</category>
    <event>Flood</event>
    <urgency>Expected</urgency>
    <severity>Severe</severity>
    <certainty>Likely</certainty>
    <headline>Flood warning for the lower river basin</headline>
    <description>River levels expected to exceed flood stage within 12 hours.</description>
    <area>
      <areaDesc>Lower River Basin</areaDesc>
      <polygon>49.20,16.60 49.20,16.80 49.05,16.80 49.05,16.60 49.20,16.60</polygon>
    </area>
  </info>
</alert>

The same alert can be sent as JSON with Content-Type: application/json.

Troubleshooting

SymptomLikely causeFix
401 invalid or revoked api keyWrong/missing key, key revoked, or source deactivatedVerify the X-API-Key value; contact TerraGuard if it should be active
422 validation errorMissing required envelope field, or malformed XML/JSONRead the error message; ensure identifier, sender, sent, status, msgType, scope, and ≥1 info are present
413Payload > 8 MiBSplit or trim the message
202 but status: UNPROFILEDYour source's transformation config isn't completeNo data lost; contact TerraGuard to finalize the mapping
Connection refused / timeoutWrong endpoint, or network/firewallConfirm the endpoint URL with TerraGuard; retry transient failures

FAQ

Which CAP version and formats do you accept? CAP v1.2, as either XML or JSON. The format is auto-detected, but setting Content-Type is recommended.

How do I get an API key? TerraGuard issues it during onboarding and shows it to you once. Store it securely.

My key leaked — what now? Contact TerraGuard. The key is revoked immediately and a new one is issued; the old one stops working at once.

How do I update or cancel an alert I already sent? Reuse the original identifier with msgType = Update (to revise) or Cancel (to withdraw).

Will retrying create duplicate events? No. TerraGuard de-duplicates by identifier and by content hash, so retries are safe.

What's the maximum message size? 8 MiB per request.

How should I send the location? A <polygon> or <circle> gives precise placement. If you can only send area geocodes (no coordinates), TerraGuard places the event at the country/region centroid.

Can I send alerts in multiple languages? Yes — include one <info> block per language. TerraGuard uses the one matching your configured language.

What does UNPROFILED mean in the response? Your message was received and safely stored, but your source's mapping isn't finished yet (or the message couldn't be placed). Nothing is lost — it's processed once the configuration is complete.

Is there a sandbox / test environment? Use status = Test or Exercise for non-production messages, and coordinate a test setup with TerraGuard during onboarding.

Are there rate limits? There's no hard per-message rate limit beyond the 8 MiB size cap, but please send at a reasonable cadence. If you expect high volume or bursts, let TerraGuard know in advance.

How do I confirm my alert became an event? A 202 with status: accepted means it was processed. Keep the raw_record_id from the response; TerraGuard can use it to trace any specific submission.

Who do I contact for help? Use the contact provided during onboarding, and include the raw_record_id (and the alert identifier) for anything you want investigated.

On this page