Skip to main content
Forte delivers signed webhook events to your backend endpoint whenever a payment status changes. For VDG purchases, deliver the item to the user only after receiving a payment_approved event.

Setup Overview

1

Authenticate

Obtain an access token using your client credentials.
2

Create a subscription

Register your webhook endpoint with Forte via POST /notifications/v1/subscriptions.
3

Receive and verify events

Forte will POST signed events to your endpoint. Verify the signature using your signing_key and respond with 200.

Managing Subscriptions

Create a Subscription

POST /notifications/v1/subscriptions
Authorization: Bearer {{access_token}}
Content-Type: application/json

{
  "endpoint": "https://yourdomain.com/webhooks/forte",
  "description": "Production payment events"
}
Response:
{
  "data": {
    "id": "c83ff48a-cd80-4f02-b63f-2155a27682cd",
    "endpoint": "https://yourdomain.com/webhooks/forte",
    "description": "Production payment events",
    "signing_key": "43dec7af-275d-4c5f-b502-c9772858daab",
    "status": "enabled",
    "version": "1"
  }
}
Store the signing_key securely. It is used to verify the authenticity of all incoming webhook events.
Subscription limits
EnvironmentMax enabled subscriptions
Production1
Sandbox / Development3
Attempting to enable a subscription beyond this limit returns 429.

List Subscriptions

GET /notifications/v1/subscriptions
Authorization: Bearer {{access_token}}

Enable / Disable a Subscription

# Enable
POST /notifications/v1/subscriptions/{id}/enable
Authorization: Bearer {{access_token}}

# Disable
POST /notifications/v1/subscriptions/{id}/disable
Authorization: Bearer {{access_token}}

Update a Subscription

PATCH /notifications/v1/subscriptions/{id}
Authorization: Bearer {{access_token}}
Content-Type: application/json

{
  "endpoint": "https://yourdomain.com/webhooks/forte-v2",
  "description": "Updated description"
}

Delete a Subscription

DELETE /notifications/v1/subscriptions/{id}
Authorization: Bearer {{access_token}}
Subscription deletion is irreversible.

Test a Subscription

Send a test event to confirm your endpoint is reachable:
POST /notifications/v1/subscriptions/{id}/test
Authorization: Bearer {{access_token}}
Returns 200 if your endpoint responds with 200, otherwise 502.

Receiving Webhooks

Your endpoint must respond with HTTP 200 for every webhook received.
If Forte does not receive a 200, it will retry 3 times before marking the webhook as failed. Subscriptions that repeatedly fail may be automatically disabled.

Verifying Signatures

Forte signs all webhooks with HMAC-SHA256 using the signing_key returned when you created the subscription. The signature is included in the X-Forte-Payments-Webhook-Signature request header. Always verify this signature before processing any payload.

Replaying Webhooks

If your endpoint was unavailable during a period, replay all webhooks from that window:
POST /notifications/v1/webhooks/replay?start_timestamp={{utc_timestamp}}&end_timestamp={{utc_timestamp}}
Authorization: Bearer {{access_token}}

Webhook Payloads

Payment Status Flow

Created → Approved   (deliver item)
Created → Declined   (do not deliver)
Created → Expired    (do not deliver)
Approved, Declined, and Expired are terminal states. No further events follow.

Payment Created

Sent when the user initiates a payment session.
{
  "event_type": "payment_created",
  "timestamp": "1725481536",
  "version": 1,
  "event_payload": {
    "payment_intent_id": "eda5d152-b75c-4f44-bb5e-65308518def9",
    "payment_status": "Created",
    "payment_method": "credit",
    "amount": "2.99",
    "currency": "EUR",
    "item_title": "Bundle of Gold",
    "item_desc": "1,000 Gold Coins",
    "customer_id": "3bd8c4f5-d25e-4260-b401-c5ce4e8bcc9a"
  }
}

Payment Approved

Sent when payment settles. Deliver the item to the user upon receiving this event.
{
  "event_type": "payment_approved",
  "timestamp": "1725481561",
  "version": 1,
  "event_payload": {
    "payment_intent_id": "eda5d152-b75c-4f44-bb5e-65308518def9",
    "payment_status": "Approved",
    "payment_method": "credit",
    "amount": "2.99",
    "currency": "EUR",
    "item_title": "Bundle of Gold",
    "item_desc": "1,000 Gold Coins",
    "customer_id": "3bd8c4f5-d25e-4260-b401-c5ce4e8bcc9a"
  }
}

Payment Declined

Sent when the card is declined or a crypto transaction fails.
{
  "event_type": "payment_declined",
  "timestamp": "1725481601",
  "version": 1,
  "event_payload": {
    "payment_intent_id": "b3e6a9bb-54f8-4fb5-8732-c3b334ec1a39",
    "payment_status": "Declined",
    "payment_method": "credit",
    "amount": "2.99",
    "currency": "EUR",
    "item_title": "Bundle of Gold",
    "item_desc": "1,000 Gold Coins",
    "customer_id": "3bd8c4f5-d25e-4260-b401-c5ce4e8bcc9a"
  }
}
If a card is declined before a 3DS challenge is presented, payment_declined fires immediately with no preceding payment_created event.

Payment Expired

Sent when the user is inactive for 30 minutes and the session times out.
{
  "event_type": "payment_intent_expired",
  "timestamp": "1725481601",
  "version": 1,
  "event_payload": {
    "payment_intent_id": "afb168c8-b951-429f-9ccf-83bf3e03f6e3",
    "payment_status": "Expired",
    "payment_method": null,
    "amount": "2.99",
    "currency": "EUR",
    "item_title": "Bundle of Gold",
    "item_desc": "1,000 Gold Coins",
    "customer_id": "3bd8c4f5-d25e-4260-b401-c5ce4e8bcc9a"
  }
}