Skip to main content

What are Webhooks?

Webhooks are HTTP notifications sent by Owem to your application when important events occur. Instead of constant polling, you receive data as soon as something happens.

Real Time

Receive notifications instantly.

Reliable

Automatic retry system on failures.

Secure

Validate origin by IP and headers.

Flexible

Configure which events you want to receive.

How It Works

1

Configure Webhook

Register your endpoint URL in the dashboard or via API.
2

Event Occurs

A payment is confirmed, transfer completed, etc.
3

Owem Sends

We POST to your URL with the event data.
4

You Process

Your application processes the event and responds with 200 OK.

Event Catalog

EventTrigger
pix_in:qrcode_paidPayment made via QR Code (PIX IN).
pix_in:creditedCredit received via PIX key.
pix_in:refunded_processingPIX IN refund initiated (returns succeeded/failed).
pix_in:refunded_med_processingPIX IN refund initiated by MED (returns succeeded/failed).
pix_out:processingPIX OUT transfer registered (returns succeeded/failed).
pix_out:refunded_processingPIX OUT refund initiated (returns succeeded/failed).
med:receivedMED (Special Refund Mechanism) received.
Use "*" in the configuration to receive all events, or list specific events.

Payload Structure

Top-Level Fields

FieldTypeDescription
webhookIdstringWebhook configuration ID that originated the event.
userIdstringOwner user.
accountIdstringAccount related to the event.
eventstringEvent type (e.g., pix_out:processing).
objectobjectEvent-specific data.

object Fields — PIX events

FieldTypeDescription
idstringEntry identifier.
externalIdstringClient-defined ID (idempotency/reconciliation).
idempotencyKeystringEntry idempotency key.
typeenumcredit or debit.
reasonenumAccounting reason (e.g., pix_out:processing).
statusenumprocessing, succeeded, failed.
grossAmountnumberGross amount.
feeAmountnumberApplied fee.
netAmountnumberNet amount.
endToEndIdstringPIX E2E identifier.
parentEndToEndIdstringOriginal E2E in refunds/returns.
payerobjectPayer data (ispb, cpfCnpj, name, agency, accountNumber).
receiverobjectReceiver data.
createdAtnumberEpoch millis (creation).
updatedAtnumberEpoch millis (last update).

Example — pix_out:processing

{
  "webhookId": "wh_abc123",
  "userId": "usr_abcdef12",
  "accountId": "987654321000",
  "event": "pix_out:processing",
  "object": {
    "id": "E000111222333444555AAA999BBB000CCC",
    "externalId": "TX-20250101-001",
    "idempotencyKey": "debit:pix_out:processing:E000111222333444555AAA999BBB000CCC",
    "type": "debit",
    "reason": "pix_out:processing",
    "status": "succeeded",
    "grossAmount": 100.0,
    "feeAmount": 0.5,
    "netAmount": 99.5,
    "endToEndId": "E000111222333444555AAA999BBB000CCC",
    "parentEndToEndId": null,
    "payer": {
      "ispb": "12345678",
      "personType": "company",
      "cpfCnpj": "11111111000191",
      "name": "EXAMPLE COMPANY LTD",
      "agency": "0001",
      "accountNumber": "987654321000"
    },
    "receiver": {
      "ispb": "87654321",
      "personType": "person",
      "cpfCnpj": "12345678900",
      "name": "MARIA SILVA",
      "agency": "0001",
      "accountNumber": "300543881811"
    }
  }
}

object Fields — med:received event

FieldTypeDescription
endToEndIdstringE2E identifier related to the MED.
detailsstringMED reason description.
medIdstringUnique MED ID.
dtHrCreationReasonstringISO-8601 date/time of MED creation.
entryIdstringLinked txId (paid QR).

Example — med:received

{
  "webhookId": "wh_abc123",
  "userId": "usr_abcdef12",
  "accountId": "987654321000",
  "event": "med:received",
  "object": {
    "endToEndId": "E000111222333444555AAA999BBB000CCC",
    "details": "Customer reports product not received.",
    "medId": "med_123e4567-e89b-12d3-a456-426614174000",
    "dtHrCreationReason": "2025-01-01T00:02:57.933Z",
    "entryId": "f929fba7e3744b6ea1def9bafe"
  }
}

Security

IP Validation

Validate that the webhook came from Owem by checking the source IP:
Owem IP
34.134.50.53
35.238.101.57
const OWEM_IPS = ["34.134.50.53", "35.238.101.57"]

app.post("/webhook", (req, res) => {
  const clientIp = req.headers["x-forwarded-for"] || req.socket.remoteAddress

  if (!OWEM_IPS.includes(clientIp)) {
    return res.status(403).send("Forbidden")
  }

  // Process webhook
  res.status(200).send("OK")
})

HTTPS Required

Your endpoint must use HTTPS with a valid certificate.

Delivery and Timeout

  • Respond within 3 seconds with HTTP 2xx (200/201/204) to confirm receipt.
  • Responses > 3s or 4xx/5xx codes count as delivery failure.
  • On failure, Owem applies redelivery with exponential backoff.
Multiple consecutive failures may deactivate the webhook until manual review.

Callback Authentication

If an authHeader is configured in your webhook configuration, Owem will send that value in the Authorization header on all calls.
Recommendation: validate source IP + authorization header on your endpoint.

Endpoint Requirements

RequirementDescription
ProtocolHTTPS required
MethodAccept POST
TimeoutRespond within 3 seconds
ResponseStatus 2xx for success
Content-TypeAccept application/json


Handler Example

const express = require("express")
const app = express()

const OWEM_IPS = ["34.134.50.53", "35.238.101.57"]

app.use(express.json())

app.post("/webhooks/owem", (req, res) => {
  // 1. Validate IP
  const clientIp =
    req.headers["x-forwarded-for"]?.split(",")[0] || req.socket.remoteAddress
  if (!OWEM_IPS.includes(clientIp)) {
    console.log("Unauthorized IP:", clientIp)
    return res.status(403).send("Forbidden")
  }

  // 2. Process event
  const { event, data } = req.body

  switch (event) {
    case "pix_in:qrcode_paid":
      console.log("Payment received:", data.txId, data.amount)
      // Update order as paid
      break

    case "pix_out:succeeded":
      console.log("Transfer completed:", data.endToEndId)
      // Update payment status
      break

    case "pix_out:failed":
      console.log("Transfer failed:", data.externalId, data.reason)
      // Notify finance team
      break

    default:
      console.log("Unhandled event:", event)
  }

  // 3. Respond quickly
  res.status(200).send("OK")
})

app.listen(3000)

Best Practices

Respond Quickly

Process in background and respond 200 immediately.

Be Idempotent

Handle duplicate webhooks without side effects.

Log Everything

Record all webhooks for debugging.

Monitor Failures

Track success rate of your endpoints.