If a carrier charges more than you declared, we refund the difference to your wallet.0850 840 15 46
Developers

Webhook guide

We send a request to your URL whenever a shipment status changes, so your software does not have to keep asking us.

Setup

  1. Add an endpoint in the panel (Panel → Webhooks). The URL must be HTTPS.
  2. Copy your signing secret — it is shown ONLY ONCE.
  3. Pick the events you want. If you pick none, you get ALL of them.
  4. Use “Send a test event” to verify your endpoint; no real shipment needed.

Events

shipment.createdA shipment was saved and its fee taken from the wallet.
shipment.labeledA shipping label was produced; a tracking number now exists.
shipment.status_changedThe shipment status changed. The payload includes the previous status.
shipment.deliveredThe shipment was delivered. Sent IN ADDITION to the status-change event, because most integrations only care about this one.
shipment.cancelledThe shipment was cancelled and its fee returned to the wallet.
pingThe test event you send from the panel, so you can verify your endpoint without creating a real shipment.

Headers

X-Shipzone-Signature`v1=<hex>` — HMAC-SHA256 of the raw body.
X-Shipzone-EventThe event name (e.g. `shipment.delivered`).
X-Shipzone-DeliveryDelivery id. It stays the SAME across retries — use it to avoid processing an event twice.

Verify the signature

Anyone who knows your URL can send you a request. Processing data without verifying the signature leaves you open to a forged “delivered” event.

# Python (Flask)
import hashlib, hmac
from flask import Flask, request

GIZLI = "panelde bir kez gösterilen imza anahtarı"
app = Flask(__name__)

@app.post("/shipzone-kanca")
def kanca():
    govde = request.get_data()          # HAM GÖVDE — parse etmeyin
    beklenen = "v1=" + hmac.new(
        GIZLI.encode(), govde, hashlib.sha256).hexdigest()

    if not hmac.compare_digest(beklenen,
                               request.headers.get("X-Shipzone-Signature", "")):
        return "", 401                  # imza tutmuyor

    olay = request.headers["X-Shipzone-Event"]
    # ... işinizi yapın ...
    return "", 200                      # 2xx = teslim alındı

Retries

Any delivery that does not return 2xx is retried: 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours. Then we give up. If you return 410 Gone we give up on that event immediately.

`X-Shipzone-Delivery` stays the SAME across retries. If you see the same id twice, do not process it again — the network may simply have eaten your response.

Endpoints can disable themselves

After 20 consecutive failures we disable the endpoint; retrying a dead address forever delays events for endpoints that do work. The panel shows why, and saving a corrected URL enables it again.

Timeout

Your endpoint gets 10 seconds. Do not do slow work inside the request: queue the event on your side and return 2xx right away.

Using the API too?

Quotes, shipment creation and address book endpoints.

API reference