Developers

Sandbox and testing

Build and test against ColiSwift’s pre-production with your own test seller and your own developer apps, then move orders forward to receive real webhooks.

The sandbox is ColiSwift’s own pre-production at https://coli.swiftmanager.net. It runs the same code as production with separate data: test sellers, test products, test orders. Production (https://coliswift.com) is the live platform with real sellers, real customers and real money — never test there.

SandboxProduction
Partner APIhttps://coli.swiftmanager.net/api/partner/v1https://coliswift.com/api/partner/v1
Token / revokehttps://coli.swiftmanager.net/api/oauth/token · /api/oauth/revokehttps://coliswift.com/api/oauth/token · /api/oauth/revoke
Consent pagehttps://coli.swiftmanager.net/oauth/authorizehttps://coliswift.com/oauth/authorize
Seller accountYours: active and with COD Drop access as soon as you sign upReal sellers, validated by ColiSwift
AppYours: you create it yourself on « Applications développeur » — no request neededCreated by ColiSwift after a review — see Go-live
WebhooksDelivered to your app’s webhook URLDelivered to your app’s webhook URL
Test helpersPOST /test/orders/{externalId}/advance, « Send test event »None (/test/* answers 404)

Getting set up

1. Create your test seller

  • Sign up as a seller on https://coli.swiftmanager.net/signup. On the sandbox the account is validated at once and its COD Drop access is opened — you can sign in immediately. (In production a new seller waits for ColiSwift’s validation, and COD Drop access is opened on request.)
  • Use your own test seller: there is one connection per app and seller, and an app you create can only be connected by the seller account that created it.
  • Create a store and a few products — in ColiSwift, or with POST /stores and POST /products once connected. Note their references.

2. Create your app

Signed in as your test seller, open Intégrations → Applications développeur. This screen exists on the sandbox only.

  • Create an app: name, description, logo, redirect URIs, the scopes it may ask for, a webhook URL and an optional event filter — the same fields ColiSwift registers for a production app (Apps and credentials).
  • The client_id, the client_secret and the webhook secret are shown once, right after creation. Copy them then: only a hash of the client secret is kept.
  • Redirect URIs: https:, or http://localhost / 127.0.0.1 / [::1] on any port. The webhook URL must be public HTTPS (never a private or loopback address): to receive webhooks on your laptop, use a tunnel.
  • Up to 5 active apps per seller account (DEVELOPER_APP_LIMIT beyond that: delete one first).
  • Edit an app at any time. Removing a scope narrows the existing connections at once (see Apps and credentials).
  • Rotate the client secret (the old one stops working immediately) or the webhook secret (the next deliveries are signed with the new one).
  • Delete an app: every connection is revoked, every token dies and pending deliveries are marked dead. A deleted app cannot be edited again (APP_DEACTIVATED); it frees a slot.
  • Each app card lists the last 20 webhook deliveries with their status (delivered, pending, failed, dead), attempt count and the HTTP status your endpoint answered.

3. Connect your seller to your app

Run the OAuth flow against https://coli.swiftmanager.net with your app’s client_id, one of its redirect URIs and PKCE. Sign in as your test seller on the consent page and approve.

4. Build and test

  • Create orders with POST /orders and read them back.
  • On the sandbox nobody works your orders: move them forward yourself with the advance helper and receive the real lead.* webhooks.
  • Check your webhook endpoint and its signature code with a test event.
  • Test the failure paths: an expired access token (refresh), a reused refresh token (connection revoked), the seller disconnecting the app from their Integrations page (401 on the next call), a scope removed from your app (403 on the calls it allowed).

Advance an order (test helper)

POST/test/orders/{externalId}/advancescope orders:write

Moves an order your app created one step through its life, the way ColiSwift’s teams would. Nothing is simulated: each step runs ColiSwift’s real status engine as the « Système ColiSwift » account (confirmation, validation and stock reservation, delivery), so the order and the webhooks you receive are exactly those of a real order. Sandbox only: in production the route does not exist (404).

Body
tostringrequired

The step to move to. Anything else is 400 VALIDATION_ERROR.

  • confirmed
  • shipped
  • delivered
  • returned
  • cancelled
curl -X POST "https://coliswift.com/api/partner/v1/test/orders/shop_10482/advance" \
  -H "Authorization: Bearer $COLISWIFT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "confirmed"
}'
200 OK
{
  "from": "open",
  "to": "confirmed",
  "stage": "confirmed",
  "allowedNext": [
    "shipped",
    "cancelled"
  ],
  "order": {
    "lead_id": "6f1c2a9e-3b7d-4c11-9a52-0d8e4b7f2c10",
    "external_id": "shop_10482",
    "order_code": "MA03112026-0042",
    "currency": "MAD",
    "country": "MA",
    "store_id": "b2d4e6f8-1a3c-4e5f-8a9b-0c1d2e3f4a5b",
    "status": "confirmed",
    "confirmed_at": "2026-11-03T10:15:05.000Z",
    "articles_amount": "398.00",
    "lines": [
      {
        "line_id": "c0a8e1f2-5d6b-4a7c-9e8f-1a2b3c4d5e6f",
        "product_id": "9e8d7c6b-5a4f-4e3d-2c1b-0a9f8e7d6c5b",
        "product_reference": "SERUM-ARGAN-30",
        "product_name": "Sérum à l'huile d'argan 30 ml",
        "variant_id": null,
        "variant_label": null,
        "quantity": 2,
        "unit_price": "199.00"
      }
    ],
    "created_at": "2026-11-03T09:58:41.000Z",
    "updated_at": "2026-11-03T10:15:05.000Z"
  }
}
Response
fromstring

The order’s stage before the call.

tostring

The step you asked for.

stagestring

The order’s stage after the call.

allowedNextstring[]

The steps you can ask for next (empty = final).

orderOrder

The order after the step, as GET /orders/{externalId} returns it (Order object).

Steps and allowed paths

open → confirmed → shipped → delivered or returned; cancelled from open or confirmed. delivered, returned and cancelled are final. The stage is read from the order’s columns, so an order a ColiSwift user moved by hand is followed too; an order in a state the helper does not handle (e.g. a delivery problem) is closed and cannot be advanced.

StepWhat changes on the orderSame asMain webhook
confirmedstatus: "confirmed", confirmed_at set: the order is confirmed and locked for shipping, stock reserved. Inside ColiSwift a warehouse holding stock for every line is chosen (in the delivery city when the order has one); a missing city / neighbourhood is filled with the warehouse’s zone. The work is recorded as done by « Système ColiSwift ».A call-centre agent confirming and validating the orderlead.confirmation_status_changed
shippedstatus: "shipped": the parcel leaves with a driver.The order put on a delivery sliplead.delivery_status_changed
deliveredstatus: "delivered"; inside ColiSwift the unit leaves the warehouse shelf.The driver marking it deliveredlead.delivery_status_changed
returnedstatus: "returned"; the stock reservation is released.The driver marking it returnedlead.delivery_status_changed
cancelledstatus: "cancelled"; from confirmed, the reservation is released.An administrator’s cancellationlead.confirmation_status_changed

Each step fires exactly the lead.* events the real gesture fires (one change can produce several, see order events). They are delivered like any event: to your app’s webhook URL, signed, while the seller’s connection is live.

Errors

HTTPCodeMeaning
400VALIDATION_ERRORto missing or not one of the five steps.
403INSUFFICIENT_SCOPEThe token lacks orders:write.
404NOT_FOUNDNo order with this externalId created by your app for this seller — another seller’s order, another app’s order or a manual order is « not found », never « forbidden ». Also the answer on production, where the helper does not exist.
409ILLEGAL_TRANSITIONThe step is not allowed from the current stage. The message names the stage and the allowed next steps (« Cannot move this order from "open" to "delivered". Allowed next: confirmed, cancelled. »), or says it is final.
409SANDBOX_NO_STOCKNo warehouse holds stock for every line of the order (in its delivery city, when it has one).
409SANDBOX_NO_ZONEThe chosen warehouse has no active city and neighbourhood to give the order.
409ORDER_IN_CALLA ColiSwift agent is calling this customer right now.
409ORDER_CHANGEDThe order changed during the call; retry.
409COURIER_MANAGEDOrders of this country are handled by a courier partner and cannot be advanced here.
409LEAD_ALREADY_INVOICEDThe order is already on an invoice; its delivery status cannot change.
503SANDBOX_SYSTEM_USER_MISSINGThe sandbox is misconfigured; tell ColiSwift.

A refusal of ColiSwift’s status engine itself (for example a line out of stock at confirmation) is answered as that engine answers it, and the order is left as it was.

Send a test event

On your app’s card, « Envoyer un événement de test » queues one test.ping event for that app only. It goes through the normal pipeline: signed with your app’s webhook secret (X-Coliswift-Signature), sent with the usual headers, retried on failure, listed in the app’s deliveries a few seconds later. It needs a webhook URL on the app (NO_WEBHOOK_URL otherwise), but no seller connection. At most one every 10 seconds per app and 30 per hour per seller (429 TEST_EVENT_RATE_LIMITED).

test.ping
{
  "data": {
    "client_id": "cs_client_0f1e2d3c4b5a69788796a5b4c3d2e1f0",
    "message": "Test event from the ColiSwift sandbox. Verify X-Coliswift-Signature with your webhook secret."
  },
  "event": "test.ping",
  "event_id": "evt_5f1c9a0b2d3e4f5a6b7c8d9e",
  "occurred_at": "2026-11-02T11:20:41.302Z",
  "seller_id": "6a1c2f0e-3b7d-4c55-9e10-2f8a4b7c9d01",
  "sequence": 4201
}

seller_id is your test seller, data.client_id your app. test.ping is not in any scope and never reaches another app; acknowledge it with 2xx like any event.

Self-checks

  • Send the same POST /orders twice: the second answer must be 200 with "duplicate": true.
  • Send a price as a JSON number: you must get 400 VALIDATION_ERROR — then fix your encoder.
  • Call with a token whose scopes lack the endpoint’s: 403 INSUFFICIENT_SCOPE with required (request a narrower scope on the authorize URL to try it).
  • Send a test event and check that your endpoint accepts its signature — then rotate the webhook secret and check that it rejects a body signed with the old one.
  • Walk one order to delivered and one to returned with the advance helper, and check that your copy matches GET /orders/{externalId} at every step.