ChatKomodo Docs Home Sign in

API reference · Integrations

Online stores

Shopify and WooCommerce order notifications: connect a store, edit the messages, test, and the signed webhook the store calls.

List connected stores

GET/v1/store-integrations

Connected online stores. Each store sends its order webhooks to webhook_url; the customer gets a WhatsApp message from session_id: new order (order_created), payment received (order_paid), shipped with tracking (order_shipped) and, for Shopify, a reminder for an unfinished checkout (abandoned_checkout, after abandoned_delay_min, cancelled when the order arrives). Each message goes once per order through the scheduled queue, so sending limits and opt-outs apply. Owner login only.

Responses

  • 200Stores
    Response fields
    • itemsarray of objectrequired
    • items[].idstringrequired
    • items[].platformstringrequired
      One of: shopify, woocommerce
    • items[].namestringrequired
      Store name used as {store}
    • items[].session_idstring | nullrequired
      The WhatsApp number that sends
    • items[].enabledbooleanrequired
    • items[].has_secretbooleanrequired
      Whether the webhook signing secret is saved (never returned)
    • items[].webhook_urlstringrequired
      Paste into the store's webhook settings
    • items[].templatesobjectrequired
    • items[].templates.order_createdobjectrequired
    • items[].templates.order_created.enabledbooleanrequired
    • items[].templates.order_created.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • items[].templates.order_paidobjectrequired
    • items[].templates.order_paid.enabledbooleanrequired
    • items[].templates.order_paid.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • items[].templates.order_shippedobjectrequired
    • items[].templates.order_shipped.enabledbooleanrequired
    • items[].templates.order_shipped.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • items[].templates.abandoned_checkoutobjectrequired
    • items[].templates.abandoned_checkout.enabledbooleanrequired
    • items[].templates.abandoned_checkout.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • items[].abandoned_delay_minintegerrequired
    • items[].abandoned_only_marketingbooleanrequired
    • items[].shop_domainstring | nullrequired
      As reported by the store's webhooks
    • items[].last_event_atinteger | nullrequired
    • items[].last_errorstring | nullrequired
    • items[].created_atintegerrequired
    • eventsarray of stringrequired
  • 403Not the owner
Request
curl "https://api.chatkomodo.com/v1/store-integrations" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY"
const res = await fetch('https://api.chatkomodo.com/v1/store-integrations', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.get(
    "https://api.chatkomodo.com/v1/store-integrations",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.chatkomodo.com/v1/store-integrations', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "items": [
    {
      "id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
      "platform": "shopify",
      "name": "Example",
      "session_id": "YOUR_DEVICE_ID",
      "enabled": true,
      "has_secret": true,
      "webhook_url": "https://example.com/webhooks/chatkomodo",
      "templates": {
        "order_created": {
          "enabled": true,
          "text": "Hi Sam, your order has shipped."
        },
        "order_paid": {
          "enabled": true,
          "text": "Hi Sam, your order has shipped."
        },
        "order_shipped": {
          "enabled": true,
          "text": "Hi Sam, your order has shipped."
        },
        "abandoned_checkout": {
          "enabled": true,
          "text": "Hi Sam, your order has shipped."
        }
      },
      "abandoned_delay_min": 1,
      "abandoned_only_marketing": true,
      "shop_domain": "string",
      "last_event_at": 1767225600000,
      "last_error": "string",
      "created_at": 1767225600000
    }
  ],
  "events": [
    "message.received"
  ]
}

Connect a store

POST/v1/store-integrations

Connect a store (at most 5). Shopify: create the webhooks in Shopify (Settings → Notifications → Webhooks, JSON) with webhook_url, then save the signing secret Shopify shows there with PUT … {secret}. WooCommerce: a strong secret is generated and returned once — paste it as the webhook secret in WooCommerce (Settings → Advanced → Webhooks, topics Order created / Order updated). Audited as store.connect.

Request body

  • platformstringrequired
    One of: shopify, woocommerce
  • namestringrequired
    1–80 characters
  • session_idstring
  • secretstring
    16–200 characters

Responses

  • 201Connected
    Response fields
    • integrationobjectrequired
    • integration.idstringrequired
    • integration.platformstringrequired
      One of: shopify, woocommerce
    • integration.namestringrequired
      Store name used as {store}
    • integration.session_idstring | nullrequired
      The WhatsApp number that sends
    • integration.enabledbooleanrequired
    • integration.has_secretbooleanrequired
      Whether the webhook signing secret is saved (never returned)
    • integration.webhook_urlstringrequired
      Paste into the store's webhook settings
    • integration.templatesobjectrequired
    • integration.templates.order_createdobjectrequired
    • integration.templates.order_created.enabledbooleanrequired
    • integration.templates.order_created.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • integration.templates.order_paidobjectrequired
    • integration.templates.order_paid.enabledbooleanrequired
    • integration.templates.order_paid.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • integration.templates.order_shippedobjectrequired
    • integration.templates.order_shipped.enabledbooleanrequired
    • integration.templates.order_shipped.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • integration.templates.abandoned_checkoutobjectrequired
    • integration.templates.abandoned_checkout.enabledbooleanrequired
    • integration.templates.abandoned_checkout.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • integration.abandoned_delay_minintegerrequired
    • integration.abandoned_only_marketingbooleanrequired
    • integration.shop_domainstring | nullrequired
      As reported by the store's webhooks
    • integration.last_event_atinteger | nullrequired
    • integration.last_errorstring | nullrequired
    • integration.created_atintegerrequired
    • secretstring
      WooCommerce: the generated signing secret, shown only now
  • 400VALIDATION_FAILED
  • 402LIMIT_REACHED
  • 403Not the owner
Request
curl -X POST "https://api.chatkomodo.com/v1/store-integrations" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "platform": "woocommerce",
  "name": "Kopi Kita",
  "session_id": "YOUR_DEVICE_ID"
}'
const res = await fetch('https://api.chatkomodo.com/v1/store-integrations', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "platform": "woocommerce",
    "name": "Kopi Kita",
    "session_id": "YOUR_DEVICE_ID"
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.post(
    "https://api.chatkomodo.com/v1/store-integrations",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    json={
        "platform": "woocommerce",
        "name": "Kopi Kita",
        "session_id": "YOUR_DEVICE_ID",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('POST', 'https://api.chatkomodo.com/v1/store-integrations', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
    'json' => [
        'platform' => 'woocommerce',
        'name' => 'Kopi Kita',
        'session_id' => 'YOUR_DEVICE_ID',
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 201
{
  "integration": {
    "id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
    "platform": "shopify",
    "name": "Example",
    "session_id": "YOUR_DEVICE_ID",
    "enabled": true,
    "has_secret": true,
    "webhook_url": "https://example.com/webhooks/chatkomodo",
    "templates": {
      "order_created": {
        "enabled": true,
        "text": "Hi Sam, your order has shipped."
      },
      "order_paid": {
        "enabled": true,
        "text": "Hi Sam, your order has shipped."
      },
      "order_shipped": {
        "enabled": true,
        "text": "Hi Sam, your order has shipped."
      },
      "abandoned_checkout": {
        "enabled": true,
        "text": "Hi Sam, your order has shipped."
      }
    },
    "abandoned_delay_min": 1,
    "abandoned_only_marketing": true,
    "shop_domain": "string",
    "last_event_at": 1767225600000,
    "last_error": "string",
    "created_at": 1767225600000
  },
  "secret": "a-long-random-secret-of-32-characters-or-more"
}

Update a store connection

PUT/v1/store-integrations/{id}

Change any of name, session_id (null = none), secret (blank keeps it), enabled, templates (any subset of the four messages), abandoned_delay_min (15–2880), abandoned_only_marketing (remind only buyers who accepted marketing). Audited as store.update.

Path parameters

  • idstringrequired

Request body

  • namestring
  • session_idstring | null
  • secretstring
  • enabledboolean
  • templatesobject
  • templates.order_createdobject
  • templates.order_created.enabledbooleanrequired
  • templates.order_created.textstringrequired
    Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
    1–1 000 characters
  • templates.order_paidobject
  • templates.order_paid.enabledbooleanrequired
  • templates.order_paid.textstringrequired
    Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
    1–1 000 characters
  • templates.order_shippedobject
  • templates.order_shipped.enabledbooleanrequired
  • templates.order_shipped.textstringrequired
    Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
    1–1 000 characters
  • templates.abandoned_checkoutobject
  • templates.abandoned_checkout.enabledbooleanrequired
  • templates.abandoned_checkout.textstringrequired
    Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
    1–1 000 characters
  • abandoned_delay_mininteger
    From 15 to 2 880
  • abandoned_only_marketingboolean

Responses

  • 200Saved
    Response fields
    • integrationobjectrequired
    • integration.idstringrequired
    • integration.platformstringrequired
      One of: shopify, woocommerce
    • integration.namestringrequired
      Store name used as {store}
    • integration.session_idstring | nullrequired
      The WhatsApp number that sends
    • integration.enabledbooleanrequired
    • integration.has_secretbooleanrequired
      Whether the webhook signing secret is saved (never returned)
    • integration.webhook_urlstringrequired
      Paste into the store's webhook settings
    • integration.templatesobjectrequired
    • integration.templates.order_createdobjectrequired
    • integration.templates.order_created.enabledbooleanrequired
    • integration.templates.order_created.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • integration.templates.order_paidobjectrequired
    • integration.templates.order_paid.enabledbooleanrequired
    • integration.templates.order_paid.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • integration.templates.order_shippedobjectrequired
    • integration.templates.order_shipped.enabledbooleanrequired
    • integration.templates.order_shipped.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • integration.templates.abandoned_checkoutobjectrequired
    • integration.templates.abandoned_checkout.enabledbooleanrequired
    • integration.templates.abandoned_checkout.textstringrequired
      Placeholders: {name} {order} {total} {items} {status} {courier} {tracking_number} {tracking_url} {checkout_url} {store}; a line whose placeholders are all empty is left out
      1–1 000 characters
    • integration.abandoned_delay_minintegerrequired
    • integration.abandoned_only_marketingbooleanrequired
    • integration.shop_domainstring | nullrequired
      As reported by the store's webhooks
    • integration.last_event_atinteger | nullrequired
    • integration.last_errorstring | nullrequired
    • integration.created_atintegerrequired
  • 400VALIDATION_FAILED
  • 403Not the owner
  • 404Not found
Request
curl -X PUT "https://api.chatkomodo.com/v1/store-integrations/ID" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "templates": {
    "order_paid": {
      "enabled": true,
      "text": "Hi {name}, we received {total} for order {order}. Thank you!"
    }
  },
  "abandoned_delay_min": 60
}'
const res = await fetch('https://api.chatkomodo.com/v1/store-integrations/ID', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "templates": {
      "order_paid": {
        "enabled": true,
        "text": "Hi {name}, we received {total} for order {order}. Thank you!"
      }
    },
    "abandoned_delay_min": 60
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.put(
    "https://api.chatkomodo.com/v1/store-integrations/ID",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    json={
        "templates": {
            "order_paid": {
                "enabled": True,
                "text": "Hi {name}, we received {total} for order {order}. Thank you!",
            },
        },
        "abandoned_delay_min": 60,
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('PUT', 'https://api.chatkomodo.com/v1/store-integrations/ID', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
    'json' => [
        'templates' => [
            'order_paid' => [
                'enabled' => true,
                'text' => 'Hi {name}, we received {total} for order {order}. Thank you!',
            ],
        ],
        'abandoned_delay_min' => 60,
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "integration": {
    "id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
    "platform": "shopify",
    "name": "Example",
    "session_id": "YOUR_DEVICE_ID",
    "enabled": true,
    "has_secret": true,
    "webhook_url": "https://example.com/webhooks/chatkomodo",
    "templates": {
      "order_created": {
        "enabled": true,
        "text": "Hi Sam, your order has shipped."
      },
      "order_paid": {
        "enabled": true,
        "text": "Hi Sam, your order has shipped."
      },
      "order_shipped": {
        "enabled": true,
        "text": "Hi Sam, your order has shipped."
      },
      "abandoned_checkout": {
        "enabled": true,
        "text": "Hi Sam, your order has shipped."
      }
    },
    "abandoned_delay_min": 1,
    "abandoned_only_marketing": true,
    "shop_domain": "string",
    "last_event_at": 1767225600000,
    "last_error": "string",
    "created_at": 1767225600000
  }
}

Disconnect a store

DEL/v1/store-integrations/{id}

Disconnect a store: its link stops working and waiting checkout reminders are dropped. Audited as store.disconnect.

Path parameters

  • idstringrequired

Responses

  • 200Disconnected
    Response fields
    • okbooleanrequired
  • 403Not the owner
  • 404Not found
Request
curl -X DELETE "https://api.chatkomodo.com/v1/store-integrations/ID" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY"
const res = await fetch('https://api.chatkomodo.com/v1/store-integrations/ID', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.delete(
    "https://api.chatkomodo.com/v1/store-integrations/ID",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('DELETE', 'https://api.chatkomodo.com/v1/store-integrations/ID', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "ok": true
}

List recent store events

GET/v1/store-integrations/{id}/events

The last 50 webhooks from the store and what was done: sent, scheduled / rescheduled / cancelled (checkout reminders), duplicate, off (message switched off), no_phone, no_session, not_marketing, ignored. Kept 30 days.

Path parameters

  • idstringrequired

Responses

  • 200Newest first
    Response fields
    • itemsarray of objectrequired
    • items[].idintegerrequired
    • items[].topicstringrequired
    • items[].refstring | nullrequired
      Order number or checkout
    • items[].outcomestringrequired
    • items[].detailstring | nullrequired
    • items[].created_atintegerrequired
  • 403Not the owner
  • 404Not found
Request
curl "https://api.chatkomodo.com/v1/store-integrations/ID/events" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY"
const res = await fetch('https://api.chatkomodo.com/v1/store-integrations/ID/events', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.get(
    "https://api.chatkomodo.com/v1/store-integrations/ID/events",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.chatkomodo.com/v1/store-integrations/ID/events', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "items": [
    {
      "id": 1,
      "topic": "string",
      "ref": "string",
      "outcome": "string",
      "detail": "string",
      "created_at": 1767225600000
    }
  ]
}

Send a test store message

POST/v1/store-integrations/{id}/test

Send one message (event, default order_created) filled with a sample order to phone, through the queue. 10 per hour per store.

Path parameters

  • idstringrequired

Request body

  • phonestringrequired
  • eventstring
    One of: order_created, order_paid, order_shipped, abandoned_checkout

Responses

  • 200Queued
    Response fields
    • okbooleanrequired
    • scheduled_idstringrequired
  • 400VALIDATION_FAILED
  • 403Not the owner
  • 404Not found
  • 409NO_SESSION — choose the sending number first
  • 429Too many tests
Request
curl -X POST "https://api.chatkomodo.com/v1/store-integrations/ID/test" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "phone": "+447700900123",
  "event": "order_shipped"
}'
const res = await fetch('https://api.chatkomodo.com/v1/store-integrations/ID/test', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "phone": "+447700900123",
    "event": "order_shipped"
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.post(
    "https://api.chatkomodo.com/v1/store-integrations/ID/test",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    json={
        "phone": "+447700900123",
        "event": "order_shipped",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('POST', 'https://api.chatkomodo.com/v1/store-integrations/ID/test', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
    'json' => [
        'phone' => '+447700900123',
        'event' => 'order_shipped',
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "ok": true,
  "scheduled_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X"
}

Receive a store webhook

POST/hooks/store/{token}Signed by the store

Where Shopify / WooCommerce send order webhooks (webhook_url). No bearer token: the body must be signed with the store's secret (HMAC-SHA256, base64) in X-Shopify-Hmac-Sha256 or X-WC-Webhook-Signature; the topic comes from X-Shopify-Topic / X-WC-Webhook-Topic. WooCommerce's address check (webhook_id=<n>) is answered with 200. Shopify topics: orders/create, orders/paid, orders/fulfilled, orders/partially_fulfilled, fulfillments/create, fulfillments/update, checkouts/create, checkouts/update, checkouts/delete, orders/cancelled. WooCommerce: order.created, order.updated (processing = paid, completed = shipped; tracking from Shipment Tracking / AfterShip order meta).

Path parameters

  • tokenstringrequired

Responses

  • 200Handled
    Response fields
    • okbooleanrequired
    • outcomestring
  • 401BAD_SIGNATURE or NO_SECRET
  • 404Unknown link
  • 429More than 300 a minute
Request
curl -X POST "https://api.chatkomodo.com/hooks/store/YOUR_STORE_TOKEN"
const res = await fetch('https://api.chatkomodo.com/hooks/store/YOUR_STORE_TOKEN', {
  method: 'POST',
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.post(
    "https://api.chatkomodo.com/hooks/store/YOUR_STORE_TOKEN",
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('POST', 'https://api.chatkomodo.com/hooks/store/YOUR_STORE_TOKEN', [
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "ok": true,
  "outcome": "string"
}