Skip to main content

Overview

Webhooks are a way for your application to receive real-time notifications when events occur in your account. When an event occurs, we send an HTTP POST request to the webhook’s configured URL. You can use webhooks to trigger custom code, workflows, or integrations in your application.

Creating Webhooks

You can create and manage webhooks directly from the JustPaid dashboard:
  1. Navigate to SettingsDeveloperWebhooks
  2. Click Create Webhook URL
  3. Enter your webhook endpoint URL
  4. Select the event types you want to subscribe to
  5. Click Save
Each webhook includes a signing secret that you can use to verify the authenticity of incoming requests.

Webhook Headers

Each webhook request includes the following headers for verification:
HeaderDescription
X-JustPaid-TimestampUnix timestamp when the webhook was sent
X-JustPaid-SignatureHMAC-SHA256 signature in format v1={sha256_hex}

Signature Verification

To verify a webhook signature:
  1. Get the raw request body
  2. Concatenate the timestamp and body: {timestamp}.{body}
  3. Compute HMAC-SHA256 using your webhook signing secret
  4. Compare with the provided signature
import hmac
import hashlib

def verify_justpaid_webhook(payload_body: bytes, timestamp: str, signature: str, secret: str) -> bool:
    expected_sig = hmac.new(
        secret.encode('utf-8'),
        f"{timestamp}.{payload_body.decode('utf-8')}".encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    provided_sig = signature.replace("v1=", "")
    return hmac.compare_digest(expected_sig, provided_sig)

Webhook Events

The following events can trigger a webhook:
Event TypeDescription
INVOICE_PAYMENT_STATUS_CHANGEPayment status changed on an invoice
INVOICE_STATUS_CHANGEInvoice status changed (e.g., draft → sent)
INVOICE_CREATEDA new invoice was created
INVOICE_UPDATEDAn existing invoice was updated
CUSTOMER_CREATEDA new customer was created
CUSTOMER_CONTRACT_CREATEDA new contract was created for a customer
PRODUCT_CREATEDA new product was created
PRODUCT_UPDATEDAn existing product was updated
CREDIT_MEMO_CREATEDA new credit memo was created
CREDIT_MEMO_UPDATEDAn existing credit memo was updated
CREDIT_MEMO_STATUS_CHANGECredit memo status changed

INVOICE_PAYMENT_STATUS_CHANGE

Triggered when the payment status of an invoice changes. Possible statuses: SCHEDULED, PROCESSED, SENT, NEED_ACTION, COMPLETED, FAILED, CANCELLED, VOIDED
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "INVOICE_PAYMENT_STATUS_CHANGE",
  "data": {
    "object": {
      "invoice_payment_uuid": "d0b1c4c0-4b1e-4b3e-8b4b-1f1d8b1d8b1d",
      "status": "COMPLETED"
    }
  }
}

INVOICE_STATUS_CHANGE

Triggered when an invoice’s status changes (e.g., from draft to sent, or sent to paid).
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "INVOICE_STATUS_CHANGE",
  "data": {
    "object": {
      "uuid": "inv_123...",
      "status": "SENT",
      "previous_status": "DRAFT"
    }
  }
}

INVOICE_CREATED

Triggered when a new invoice is created.
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "INVOICE_CREATED",
  "data": {
    "object": {
      "uuid": "inv_123...",
      "invoice_number": "INV-2026-001",
      "customer_uuid": "cust_456...",
      "total_amount": 1500.00,
      "currency": "USD",
      "status": "DRAFT"
    }
  }
}

INVOICE_UPDATED

Triggered when an existing invoice is updated. This includes changes to line items, amounts, dates, or any other invoice fields.
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "INVOICE_UPDATED",
  "data": {
    "object": {
      "uuid": "inv_123...",
      "invoice_number": "INV-2026-001",
      "customer_uuid": "cust_456...",
      "total_amount": 1750.00,
      "currency": "USD",
      "status": "DRAFT"
    }
  }
}

CUSTOMER_CREATED

Triggered when a new customer is created.
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "CUSTOMER_CREATED",
  "data": {
    "object": {
      "uuid": "cust_456...",
      "name": "Acme Corporation",
      "email": "billing@acme.com"
    }
  }
}

CUSTOMER_CONTRACT_CREATED

Triggered when a new contract is created for a customer.
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "CUSTOMER_CONTRACT_CREATED",
  "data": {
    "object": {
      "uuid": "contract_789...",
      "customer_uuid": "cust_456...",
      "name": "Enterprise License Agreement",
      "start_date": "2026-01-01",
      "end_date": "2026-12-31"
    }
  }
}

PRODUCT_CREATED

Triggered when a new product is created.
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "PRODUCT_CREATED",
  "data": {
    "object": {
      "uuid": "prod_abc...",
      "name": "Enterprise Plan",
      "category": "Software",
      "billing_alias": "ENT-001",
      "accounting_item": {
        "uuid": "acc_xyz...",
        "name": "Software Revenue",
        "external_id": "4000"
      }
    }
  }
}

PRODUCT_UPDATED

Triggered when an existing product is updated.
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "PRODUCT_UPDATED",
  "data": {
    "object": {
      "uuid": "prod_abc...",
      "name": "Enterprise Plan Pro",
      "category": "Software",
      "billing_alias": "ENT-002"
    }
  }
}

CREDIT_MEMO_CREATED

Triggered when a new credit memo is created. Credit memos are used to handle refunds and credits.
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "CREDIT_MEMO_CREATED",
  "data": {
    "object": {
      "uuid": "cm_123...",
      "customer_uuid": "cust_456...",
      "amount": 500.00,
      "currency": "USD",
      "reason": "Service credit",
      "status": "DRAFT"
    }
  }
}

CREDIT_MEMO_UPDATED

Triggered when an existing credit memo is updated.
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "CREDIT_MEMO_UPDATED",
  "data": {
    "object": {
      "uuid": "cm_123...",
      "customer_uuid": "cust_456...",
      "amount": 600.00,
      "currency": "USD",
      "reason": "Updated service credit",
      "status": "DRAFT"
    }
  }
}

CREDIT_MEMO_STATUS_CHANGE

Triggered when a credit memo’s status changes.
{
  "id": "evt_abc123...",
  "object": "event",
  "api_version": "v1",
  "created": "2026-01-27T10:30:00.000000+00:00",
  "type": "CREDIT_MEMO_STATUS_CHANGE",
  "data": {
    "object": {
      "uuid": "cm_123...",
      "status": "APPLIED",
      "previous_status": "DRAFT"
    }
  }
}

Delivery

  • Webhooks are delivered asynchronously
  • Automatic retries on failure (up to 3 attempts with exponential backoff)
  • Each event has a unique id for idempotency
  • Events are delivered in order when possible, but you should handle out-of-order delivery

Best Practices

  1. Respond quickly - Return a 2xx status code within 30 seconds
  2. Process asynchronously - Queue webhook events for background processing
  3. Verify signatures - Always validate the X-JustPaid-Signature header
  4. Handle duplicates - Use the event id for idempotency
  5. Log events - Keep records for debugging and auditing