API reference

Pounce API

Everything you need to send proactive WhatsApp property alerts from your portal or CRM. One opt-in endpoint. One alert endpoint. We handle the rest.

Base URL https://api.pounceinfra.com/v1
Getting started

Overview

The Pounce API is a REST API that accepts JSON and returns JSON. It has two core endpoints your platform needs to call:

  • /v1/optin — register a buyer's phone number and consent when they save a search
  • /v1/alert — fire a WhatsApp alert when a listing matches a subscribed buyer

Everything else — WhatsApp Business API delivery, Meta template management, deduplication, POPIA consent logging, and reply handling — is managed entirely by Pounce. Your integration is 3 to 4 engineering days.

How it flows

A buyer saves a search on your portal → calls POST /v1/optin → buyer receives a WhatsApp verification message → replies YES → consent recorded. When a new listing matches their criteria → your CRM calls POST /v1/alert → Pounce delivers the WhatsApp in under 90 seconds → buyer replies → Pounce sends a webhook to your callback URL.

All requests use HTTPS. HTTP requests will be rejected with a 301 redirect. Always use https://api.pounceinfra.com.
request format
all requests
POST https://api.pounceinfra.com/v1/alert Headers: Authorization: Bearer pk_live_xxxxxxxxxxxx Content-Type: application/json Accept: application/json // All responses return JSON // Successful responses: 200 OK // Errors: 4xx with {error, message, code}
example response envelope
200 OK
{ "status": "delivered", "message_id": "pnc_01HV8XKMT5...", "ms": 84, "deduped": false }
Getting started

Authentication

Pounce uses Bearer token authentication. Every request must include your API key in the Authorization header.

API key formats

  • Live key: pk_live_ prefix — fires real WhatsApp messages
  • Test key: pk_test_ prefix — sandbox mode, no real messages sent

Getting your API key

API keys are issued as part of the partner onboarding process. Contact hello@pounceinfra.com to request access. You will receive both a live key and a test key.

Keep your API key secret. Never expose it in client-side code, public repositories, or logs. If a key is compromised, contact us immediately and we will rotate it.

Key scopes

Each API key is scoped to a single partner account. Keys cannot be used across multiple portal integrations. If you operate multiple portals, contact us for a multi-portal account structure.

authenticating a request
JavaScript
const response = await fetch( 'https://api.pounceinfra.com/v1/alert', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.POUNCE_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify(payload) } );
curl example
cURL
curl -X POST \ https://api.pounceinfra.com/v1/alert \ -H "Authorization: Bearer pk_test_xxxx" \ -H "Content-Type: application/json" \ -d '{"event_type":"new_listing",...}'
Getting started

Sandbox & testing

Use your pk_test_ key during development. In test mode, the API behaves identically to live mode but no real WhatsApp messages are sent. Responses return simulated delivery receipts so you can test your integration end-to-end.

Test phone numbers

In sandbox mode, any E.164-formatted phone number is accepted. Use +27000000001 through +27000000010 as designated test numbers — these return specific simulated responses:

  • +27000000001 — always returns delivered
  • +27000000002 — simulates deduplication (returns deduped: true)
  • +27000000003 — simulates opt-in not found (returns 422)
  • +27000000004 — simulates Meta delivery failure (returns 503)
Webhook testing: In sandbox mode, reply webhooks are fired to your callback URL within 5 seconds of the alert request, simulating an instant buyer YES reply. Use this to test your reply handling end-to-end without waiting for a real buyer.
test mode header
test key — no real messages
// Use pk_test_ prefix — sandbox mode 'Authorization': 'Bearer pk_test_a1b2c3d4e5f6...' // Response is identical to live { "status": "delivered", "message_id": "pnc_test_01HV...", "ms": 84, "sandbox": true }
Endpoints

Register opt-in

POST /v1/optin

Register a buyer's phone number and record their consent to receive WhatsApp property alerts. Call this when a buyer saves a search on your portal or CRM and enters their phone number.

Pounce sends the buyer a WhatsApp verification message. When they reply YES, consent is recorded and they will begin receiving alerts. The opt-in is double-confirmed — both the form submission and the WhatsApp reply are required.

Request parameters

FieldTypeRequiredDescription
phonestringRequiredBuyer's phone number in E.164 format. Example: +27720000123
namestringRequiredBuyer's first name. Used to personalise the verification message.
search_criteriaobjectRequiredThe saved search parameters — used for matching. See search_criteria object below.
subscriber_idstringOptionalYour internal buyer/user ID. Returned in all subsequent webhooks for easy lookup.
portal_idstringOptionalYour portal identifier if you operate multiple portals under one account.
consent_timestampISO 8601OptionalWhen the buyer submitted the opt-in form. Defaults to request time if omitted.

search_criteria object

FieldTypeDescription
locationstringArea, suburb, or city. Example: "Bryanston, Sandton"
property_typestring"house", "apartment", "townhouse", "land", "commercial"
min_priceintegerMinimum price in local currency (no decimals)
max_priceintegerMaximum price in local currency
min_bedsintegerMinimum number of bedrooms
currencystringISO 4217 currency code. Example: "ZAR", "AED", "BRL"
request
POST /v1/optin
{ "phone": "+27720000123", "name": "Sarah", "subscriber_id": "usr_0042", "search_criteria": { "location": "Bryanston, Sandton", "property_type": "house", "min_price": 3000000, "max_price": 5000000, "min_beds": 3, "currency": "ZAR" } }
response — 200 OK
200 OK
{ "status": "pending_confirmation", "optin_id": "opt_01HV8XKMT5...", "phone": "+27720000123", "message": "Verification WhatsApp sent", "expires_at": "2026-05-20T18:42:00Z" } // Buyer receives WhatsApp: // "Hi Sarah! Reply YES to activate // instant property alerts from // [Your Portal]. Reply STOP anytime."
Endpoints

Send alert

POST /v1/alert

Fire a proactive WhatsApp alert to a subscribed buyer when a new listing matches their saved search criteria. Call this endpoint alongside your existing email alert dispatch — same trigger, new channel.

Pounce validates the opt-in, runs deduplication, selects the correct pre-approved Meta template, populates it with listing data, and delivers via WhatsApp Business API. Median delivery time is under 90 seconds from listing publish.

Request parameters

FieldTypeRequiredDescription
event_typestringRequired"new_listing", "price_reduction", or "back_on_market"
phonestringRequiredBuyer's phone number in E.164 format. Must match a confirmed opt-in.
propertyobjectRequiredListing details — see property object below.
property_idstringRequiredYour unique listing identifier. Used for deduplication — same phone + property_id within 2 hours will be suppressed.
agentobjectOptionalAgent name and contact details to include in the message.
callback_urlstringOptionalOverride the account-level webhook URL for this specific alert.

property object

FieldTypeDescription
addressstringProperty address or suburb. Included in the WhatsApp message.
priceintegerListing price in local currency (no decimals).
currencystringISO 4217 code. Example: "ZAR", "AED", "BRL".
bedroomsintegerNumber of bedrooms.
bathroomsintegerNumber of bathrooms.
property_typestringHuman-readable type string e.g. "3-bed house".
listing_urlstringFull URL to the listing on your portal. Included as a link in the message.
request
POST /v1/alert
{ "event_type": "new_listing", "property_id": "listing-8842", "phone": "+27720000123", "property": { "address": "14 Marlowe Rd, Sandton", "property_type": "3-bed house", "price": 3950000, "currency": "ZAR", "bedrooms": 3, "bathrooms": 2, "listing_url": "https://yourportal.com/l/8842" }, "agent": { "name": "Pam Golding Properties", "phone": "+27110000000" } }
response — 200 OK
200 OK
{ "status": "delivered", "message_id": "pnc_01HV8XKMT5...", "ms": 84, "deduped": false, "template": "new_listing_v3", "phone": "+27720000123" }
deduped response
200 OK — suppressed
{ "status": "suppressed", "deduped": true, "reason": "duplicate_within_window", "original_id": "pnc_01HV8XK..." } // No alert sent — buyer already received // this listing within the 2-hour window
Webhooks

Buyer reply callback

When a buyer replies to a Pounce alert, Pounce sends a POST request to your configured callback URL within 5 seconds of the reply being received.

Configure your callback URL in your partner dashboard, or pass callback_url per-request on the alert endpoint.

Reply types

  • YES — buyer wants to book a viewing. Route to your booking flow.
  • CALL — buyer wants to call the agent directly.
  • STOP — buyer is opting out. Pounce suppresses all future alerts automatically. Webhook fires so you can update your own records.
  • OTHER — any other text reply. Raw text included in webhook payload.
Respond with 200 OK within 5 seconds to acknowledge receipt. If Pounce does not receive a 200, it will retry 3 times with exponential backoff (5s, 30s, 5min).

Securing your webhook

Every webhook includes a X-Pounce-Signature header — an HMAC-SHA256 signature of the raw request body using your webhook secret. Verify this before processing any webhook payload.

YES reply webhook payload
POST → your callback_url
{ "event": "reply.received", "reply_type": "YES", "message_id": "pnc_01HV8XKMT5...", "property_id": "listing-8842", "subscriber_id": "usr_0042", "phone": "+27720000123", "replied_at": "2026-05-20T08:43:12Z", "latency_ms": 84 }
verifying the signature
Node.js
const crypto = require('crypto'); function verifyWebhook(body, sig, secret) { const expected = crypto .createHmac('sha256', secret) .update(body) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(sig), Buffer.from(expected) ); }
Reference

Deduplication

Pounce automatically prevents a buyer receiving duplicate alerts for the same property. This is the core technical moat — if a buyer is registered across multiple portals or channels, they will only ever receive one alert per property.

How it works

Pounce generates a deduplication key from a hash of phone + property_id. If the same key is seen within a 2-hour window, the second alert is suppressed and returned with "status": "suppressed", "deduped": true. Your system can treat this as a 200 success — no action required.

Cross-portal deduplication

If your buyer is registered via two separate portals that both call Pounce, deduplication fires across both. This means you can confidently offer Pounce to buyers without worrying about spam — they will never receive the same listing twice regardless of how many partner platforms they use.

Deduplication is automatic. You do not need to implement any deduplication logic on your side. Simply call POST /v1/alert for every match — Pounce handles the rest.
dedup key generation
internal — for reference
// Pounce generates this key internally // Your integration needs no dedup logic key = SHA256(phone + property_id) ttl = 7200 // 2 hours in seconds // If key exists in cache → suppress // If key absent → deliver + cache // Works across portals — same buyer // on multiple platforms = one alert
Reference

Error codes

Pounce uses standard HTTP status codes. All error responses include a JSON body with error, message, and code fields.

StatusCodeMeaning
200deliveredAlert delivered successfully.
200suppressedAlert suppressed by deduplication. Not an error — treat as success.
400invalid_payloadMalformed JSON or missing required field. Check the message field for specifics.
400invalid_phonePhone number is not in valid E.164 format.
401unauthorisedMissing or invalid API key. Check your Authorization header.
409optin_pendingOpt-in registered but buyer has not yet replied YES to the verification message.
422optin_not_foundNo confirmed opt-in exists for this phone number. Buyer must opt in before alerts can be sent.
422opted_outBuyer has replied STOP and opted out. Do not retry — remove from your alert queue.
503meta_unavailableWhatsApp Business API temporarily unavailable. Pounce will auto-retry for up to 10 minutes.
error response format
4xx error body
{ "error": "optin_not_found", "message": "No confirmed opt-in for +27720000123", "code": 422, "docs": "https://pounceinfra.com/docs" }
Reference

POPIA & GDPR compliance

Pounce is built for data privacy compliance from day one. All consent is double opt-in. All opt-outs are processed within 60 seconds. The compliance architecture is designed for POPIA (South Africa), GDPR (EU/UK), LGPD (Brazil), and PDPL (UAE/Saudi Arabia).

Data we store

  • Phone number — stored as a salted hash in the deduplication layer. Never stored in plaintext in logs.
  • Consent timestamp — when the opt-in form was submitted and when the buyer replied YES.
  • Opt-in source — which portal/CRM the opt-in came from.

Pounce does not store property browsing history, financial data, or any PII beyond what is listed above.

Right to erasure

Call POST /v1/optout with the buyer's phone number to immediately delete all stored data. The phone hash is removed from the deduplication cache, consent records are deleted, and all future alerts are suppressed. This satisfies POPIA Section 24 and GDPR Article 17.

Data processing agreement

Pounce acts as data processor. Your platform is the data controller. A standard Data Processing Agreement (DPA) is provided as part of the partner onboarding and takes a single legal review to approve. Contact hello@pounceinfra.com to request the DPA.

opt-out / right to erasure
POST /v1/optout
// Request { "phone": "+27720000123", "reason": "buyer_request" } // Response — 200 OK { "status": "opted_out", "deleted": true, "message": "All data erased", "processed_in_ms": 240 } // STOP reply also triggers this // automatically — no action needed
Reference

Quick start guide

From API key to first live alert in 3–4 engineering days. Here is the exact sequence.

Day 1 — Opt-in form

Add a phone number field to your existing saved-search confirmation screen. When the buyer submits, call POST /v1/optin with their phone and search criteria. Pounce sends a WhatsApp verification. Done.

Day 2 — Alert webhook

In your listing-match engine (the same code that dispatches email alerts), add a call to POST /v1/alert with the property data and buyer phone. Sits alongside your email dispatch — same trigger, one extra API call.

Day 3 — Reply handling

Set up your callback URL in the Pounce partner dashboard. When a buyer replies YES, Pounce sends a webhook. Route it to your booking confirmation flow or agent notification system.

Day 4 — Reporting widget

Embed the Pounce reporting widget in your agent dashboard — a single <script> tag. Shows agents their alert delivery stats, open rates, and reply rates per listing.

complete integration — Day 2
// Sits alongside your existing email dispatch // Same trigger — one extra call async function dispatchListingAlerts(listing, buyer) { // Your existing email dispatch (unchanged) await sendEmailAlert(listing, buyer); // Pounce WhatsApp alert (new — 5 lines) await fetch('https://api.pounceinfra.com/v1/alert', { method: 'POST', headers: { 'Authorization': `Bearer ${POUNCE_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ event_type: 'new_listing', property_id: listing.id, phone: buyer.phone, property: { address: listing.address, property_type: listing.type, price: listing.price, currency: 'ZAR', bedrooms: listing.beds, listing_url: listing.url } }) }); }