Support
Notifications for completion of orders created via API

How to set up notifications for API order completion

Which events count as order completion

First, determine which status in the API means the actual completion of an order. Different providers may use completed, delivered, cancelled, rejected, returned, or partially completed. Don't tie your automation to the word "success" alone: an order can go through several intermediate states and then stop due to a limit, a review, or a cancellation.

You need to handle more than just the positive outcome. If the service sends a notification about an error, cancellation, refund, or partial completion, it should also be recorded in your internal system. Otherwise, the order will remain pending in the dashboard, CRM, or bot even though further fulfillment will no longer happen.

Create a status mapping table

Don't pass the API status to the interface without processing it. Provider names and logic can change, and the same internal status sometimes combines several external ones. Store the original value separately: it will be useful for troubleshooting and cross-checking with the documentation.

  • pending, created, queued — a new order or one awaiting processing.
  • processing, in_progress, running — the order is being fulfilled.
  • completed, delivered, success — a completed order.
  • partial, partially_completed — a partially completed order.
  • cancelled, rejected, failed — a cancelled order or one that ended with an error.
  • refunded, returned — the order requires a refund or adjustment.
  • Unknown status — does not change the order card automatically and is sent for review.

The names above are given as an example scheme. The final table must be built based on the statuses of the specific API. The downside of manual mapping is that it must be maintained after the API is updated: a new status may reach the handler before a rule exists for it.

Choose webhooks, API polling, or both

A webhook is a request from the service to your URL when an order status changes. API polling works the other way around: your system requests order information at an interval. For completion notifications, webhooks are usually more convenient because the update arrives without constant requests to the status-check method.

  • Webhooks are suitable for a quick reaction: updating the order card, starting the next stage, or sending a message to the person responsible.
  • Polling is suitable if the provider does not support callback notifications or your server does not accept external requests.
  • A combined scheme uses webhooks as the primary channel and polling to find missed or stuck orders.

The downside of polling is delay and extra load on the API. The downside of webhooks is that you need to secure the endpoint, account for duplicates, and not rely on the order in which events are delivered.

Set up an endpoint to receive events

Notifications require a public HTTPS address accessible from the API service side. In the integration settings, you usually specify the handler URL, the signing secret, and the list of events: status change, completion, cancellation, error, or partial completion.

Dedicate a separate route for API events only. This makes it easier to set up logging, restrict access, set rate limits, and avoid mixing service traffic with website forms. Don't use a test environment address for production orders: after the environment is updated, the provider will continue sending events to the saved URL.

Before launch, check the request method and body format against the documentation. Most often it's a POST with JSON, but you may encounter form-data, query parameters, or a custom serialization scheme. Parsing errors should be logged; otherwise, it will be hard to distinguish an invalid payload from an application failure.

When creating an order via the API, save the identifier returned by the provider. Alongside it, store the internal order number, service type, original status, last modification time, and the original API response in a secure form. Match the incoming webhook by the provider ID, not by the channel link, service name, or customer name.

If the API allows passing an external identifier at creation, add your order number to a field like external_id or client_reference. This simplifies searching logs and resolving disputes. But don't make the external number the only key: some providers do not return it in every notification.

Don't create a new order based on an unknown ID from a webhook. An unknown event should be saved to the log and checked separately. Automatically creating a record can lead to incorrect data or processing of a forged request.

Use a clear payload structure

The exact field names depend on the API. Below is not a contract of a specific service but an example JSON event you can use as a reference when designing your internal handler. What matters is the event identifier, the provider's order ID, the status, the modification time, and diagnostic data.

{

  "event_id": "evt_7f31",

  "event_type": "order.status_changed",

  "created_at": "2025-01-15T12:40:00Z",

  "data": {

    "order_id": "provider_order_4815",

    "external_id": "internal_order_9021",

    "status": "completed",

    "completed_quantity": 1000,

    "requested_quantity": 1000

  }

}

Don't use the number of completed units as a sign of completion without a status. An order may be partially completed, and the number in the payload may be rounded, updated with a delay, or not provided at all. The downside of storing the full event body is that it may contain personal data or service fields, so such records must be masked and have a limited retention period.

Verify the signature against the raw request body

An open handler URL may receive a request not only from the API service. If the provider passes a signature, secret, or token, verify them before changing the order. A common scheme is HMAC-SHA256: the provider computes a signature from the request body bytes and a shared secret, then passes the result in an HTTP header.

The computation principle is as follows: take the raw request body, for example the JSON bytes without changes, and the integration secret. Then compute HMAC-SHA256. If the hexadecimal result matches the header value, the body has not changed since signing and the request was likely sent by a party that knows the secret.

A conditional example: HMAC_SHA256(secret, raw_body) = the signature from the X-Signature header. The header name, algorithm, and result format must be taken only from the API documentation. Some services add a timestamp or event ID to the string being signed. In that case, you cannot verify only the JSON body.

A schematic image of the data verification process using a key and glowing elements inside a transparent block.

Don't modify JSON before verifying the signature

The signature is verified against the raw request bytes, not against the JSON object that the application has already parsed and reassembled. Re-serialization can change field order, whitespace, character escaping, line breaks, or encoding. To a human, the JSON will look the same, but the byte set will change, and the HMAC will no longer match.

To avoid this, first get the raw body as bytes or a buffer, keep it in memory, compute the signature, and only parse the JSON after successful verification. Don't apply trim, encoding conversion, key sorting, or formatting to the body. In the framework middleware, check whether JSON is parsed automatically before you can access the raw body.

The downside of this scheme is that the handler becomes dependent on middleware order. If configured incorrectly, the application will only see the transformed object, and legitimate notifications will start being rejected.

Example handler with HMAC verification

Below is a conditional Python example. It shows the sequence of steps, not a ready-made integration: the headers, algorithm, signature format, and payload fields must be replaced with values from the provider's documentation.

import hmac

import hashlib

import json

from hmac import compare_digest

def handle_webhook(request):

  raw_body = request.body

  received_signature = request.headers.get("X-Signature", "")

  secret = get_webhook_secret()

  expected_signature = hmac.new(

    secret.encode("utf-8"), raw_body, hashlib.sha256

  ).hexdigest()

  if not compare_digest(expected_signature, received_signature):

    log_invalid_signature(request)

    return response(status=401)

  payload = json.loads(raw_body.decode("utf-8"))

  return process_event(payload)

For comparison, use a function that does not stop at the first mismatched character. This reduces the risk of leaking signature data through response timing. Don't pass the secret to client-side code, don't add it to the URL, and don't write it in full to logs.

Make event processing idempotent

The provider may deliver the same event several times. The reasons are common: your server took too long to respond, the connection dropped after data was saved, the endpoint temporarily returned an error, or the service started a retry according to its own rules. A retry does not mean the API created a new order.

Idempotency means that the same event changes the result only once. If you don't account for this rule, a duplicate will re-send a message to the customer, create several tasks for the manager, credit a compensation, or trigger a repeated operation.

It's best to use the event_id from the payload. Store it in a separate table or processed-events log with a unique constraint. If there is no separate ID, build a key from stable fields: the provider's order ID, event type, status, and modification time. This option is worse: with imprecise timestamps, different events may look identical.

Save the event and status in a single operation

The check "has the event been processed" and the result write must be performed atomically. Otherwise, two identical requests arriving at the same time will both see no record and trigger the action twice. A practical option is a unique index on event_id and a database transaction.

A conditional continuation of the handler looks like this:

def process_event(payload):

  event_id = payload["event_id"]

  provider_order_id = payload["data"]["order_id"]

  new_status = map_status(payload["data"]["status"])

  with database_transaction():

    if event_exists(event_id):

      return response(status=200)

    order = find_order_by_provider_id(provider_order_id)

    if order is None:

      save_unmatched_event(event_id, payload)

      return response(status=200)

    apply_status_if_allowed(order, new_status, payload)

    save_processed_event(event_id, provider_order_id)

  enqueue_follow_up_actions(event_id)

  return response(status=200)

The downside of responding with a success code for an unknown order is that the provider may not retry delivery. Therefore, unknown events must be monitored separately and resolved quickly. If the API documentation recommends a different response code for such cases, follow it.

Account for out-of-order events

Webhooks do not always arrive strictly in the order of status changes. A completion event may arrive first, followed by a delayed notification about the "in progress" status. If you simply record the last received value, a completed order will become active again.

Define allowed transitions. For example, an intermediate status cannot overwrite a final one, and a cancelled order is not moved to completed without a separate check. If the API allows adjusting the final status, save the reason, the original value, and the source of the change.

If the payload contains the order modification time, compare that, not the time the webhook was received. When the API does not pass such a timestamp, use state priorities and reconciliation via the order retrieval method. The downside of priorities is that they do not replace the actual sequence, especially if the provider allows a refund from a final status.

Acknowledge delivery quickly and move actions to a queue

Don't perform long operations before responding to the provider. Signature verification, order lookup, event recording, and status updates can usually be completed quickly. Sending a message, syncing with the CRM, generating a report, or making requests to third-party systems is better passed to a task queue.

The working order is: verify the signature, atomically save the event and status change, return a success response, then perform secondary actions. If you respond before saving, data will be lost on failure. If you respond after a long notification send, the provider may consider the delivery unsuccessful and send a duplicate.

The downside of a queue is that it adds a separate component to monitor: task errors, delays, and re-runs. But a failure in a manager notification does not block the receipt of order statuses.

Set up notifications for the team and the customer

After a status change, you don't need to notify everyone the same way. The manager usually cares about cancellations, errors, partial completion, and orders that haven't changed for a long time. The customer usually just needs a clear outcome: the order is completed, cancelled, or requires clarification.

  • Completed order — an update in the customer account or a brief message to the customer.
  • Fulfillment error — a notification to the person responsible with the reason provided by the API.
  • Partial completion — a task to review an adjustment, refund, or next action.
  • Unknown status — a log entry and a message to the technical specialist.
  • Unknown order ID — a separate check of the link between your system and the provider.

Don't send a message on every technical transition. The feed will quickly turn into noise, and an important issue will go unnoticed. An internal notification should contain the order number, service, current status, external ID, and a link to the order card.

Keep a log and reconcile unfinished orders

Logs are needed to understand whether the service sent an event, what body arrived, why the signature failed, and at what stage processing stopped. Save the receipt time, event ID, order ID, event type, signature verification result, internal status, and response code. Mask secrets, tokens, and personal data.

Separately track delivery errors, invalid signatures, unknown orders, unsupported statuses, duplicates, and events that cannot be applied due to state order. Growth in such records may indicate an API schema change, an expired secret, a route failure, or a logic error in the handler.

Periodically reconcile orders in intermediate statuses via the API data retrieval method. This check does not replace webhooks but helps detect a missed event, a queue failure, or a case where the external status changed without a correct notification.

Last Articles

New website design

What has changed in design and functionality We have updated the website to make working with it faster and more convenient. The main changes affect ..

15/08/2026 New

News SP

Good afternoon, I've collected all the news during this time.: 1. The main news is that prices for twitch viewers have been greatly reduced, while Tw..

08/04/2026 Update

We have collected all current promotions and giveaways for you until 01.01.2026

1. Use promo code "December2025" for a 15% discount for all our viewers2. We have reduced the base prices for our configurator and the most affordable..

26/12/2025 Ended

Cooperation with squads and resellers

Twitch services are working stably, so we are ready to cooperate with squads, resellers, service owners, bot owners, and many others.Individual te..

22/10/2025 For partners

Twitch viewers are stable, but there are some nuances.

We have completely updated our Twitch viewer services, and they are now working stably. We only use high-quality IP addresses for the viewers.The ..

22/10/2025 Update

Twitch Viewer Configurator and Control Panel

Hello everyone! Today, we are announcing a new feature—"Twitch Viewer Configurator". Now, you can customize any plan for your Twitch channel. Choo..

15/06/2025 New

If YouTube is blocked, where to stream now?

Greetings, I have compiled a guide for streamers, which will be very relevant at the moment. Now YouTube and twitch have disabled monetization from vi..

16/03/2022 Important

Reseller Panel API SP

We have finally developed the APINow it will be more convenient for our partner sites to work with us.To update the maximum tariffs for YouTube, an up..

02/09/2021 For partners

PARTNERS AND REFERRALS: NEW TERMS!

Due to the huge popularity of the partnership services and referral program, we have made a cooperation table. The essence is very simple: more live a..

12/08/2020 For partners

Viewer control panel [Twitch | Kick | YouTube | VK Video Live]

Build your own custom plan
Deposit funds, one-click order, discounts and bonuses are available only for registered users. Register.
If you didn't find the right service or found it cheaper, write to our support in Telegram or chat, and we will resolve any issue.
New

Telegram bot @BOT_SP_RU_BOT

Order or repeat in a minute, balance and order statuses — right in Telegram

Repeat orderOrder statusesBalance top-upPromo codes