Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.digifist.com/llms.txt

Use this file to discover all available pages before exploring further.

This page is the authoritative payload reference for every webhook Galantis registers with Shopify and every webhook event it receives from Meta. It covers the topic, the expected payload structure, the internal handler, and what the webhook drives in Galantis. For the processing behavior and downstream effects of each webhook, see Integrations — Shopify Webhooks and Integrations — Meta Webhooks. This page focuses on payload structure for developer reference.

Security

Shopify webhooks — All incoming Shopify webhooks are validated via HMAC signature verification using the X-Shopify-Hmac-Sha256 header before processing. Requests with invalid or missing signatures are rejected with a 401 response and never reach the handler. Meta webhooks — All incoming Meta webhooks are validated via signature verification using the X-Hub-Signature-256 header before processing. Invalid signatures are rejected. Both verifications use the app secret for their respective platform. Webhook payloads are never processed without a valid signature.

Shopify webhooks

Customer webhooks

customers/create Handler: ProcessShopifyCustomerCreatedJob
{
  "id": 123456789,
  "email": "customer@example.com",
  "first_name": "Jane",
  "last_name": "Smith",
  "phone": "+521234567890",
  "tags": "vip, newsletter",
  "accepts_marketing": true,
  "email_marketing_consent": {
    "state": "subscribed",
    "opt_in_level": "single_opt_in"
  },
  "sms_marketing_consent": {
    "state": "subscribed",
    "opt_in_level": "single_opt_in"
  },
  "locale": "es",
  "created_at": "2025-01-15T10:00:00-05:00",
  "updated_at": "2025-01-15T10:00:00-05:00"
}

customers/update Handler: ProcessShopifyCustomerUpdatedJob Same structure as customers/create. All fields are included in the payload — Galantis diffs the incoming data against the stored record to identify changes.
customers/delete Handler: ProcessShopifyCustomerDeletedJob
{
  "id": 123456789
}
Only the customer ID is included. Galantis uses the ID to locate and remove the corresponding contact record.
customers/marketing_consent_updated Handler: ProcessShopifyCustomerMarketingConsentUpdatedJob
{
  "id": 123456789,
  "email_marketing_consent": {
    "state": "subscribed",
    "opt_in_level": "single_opt_in",
    "consent_updated_at": "2025-01-15T10:05:00-05:00"
  },
  "sms_marketing_consent": {
    "state": "subscribed",
    "opt_in_level": "single_opt_in",
    "consent_updated_at": "2025-01-15T10:05:00-05:00"
  },
  "phone": "+521234567890",
  "updated_at": "2025-01-15T10:05:00-05:00"
}
Galantis maps the SMS/phone marketing consent state to CustomerMarketingStateEnum for the marketing_state field.
customer_tags/added Handler: ProcessShopifyCustomerTagsAddedJob
{
  "customer_id": 123456789,
  "tags_added": ["vip", "loyalty-gold"]
}

customer_tags/removed Handler: ProcessShopifyCustomerTagsRemovedJob
{
  "customer_id": 123456789,
  "tags_removed": ["loyalty-silver"]
}

Order webhooks

orders/create Handler: ProcessShopifyOrderCreatedJob
{
  "id": 987654321,
  "order_number": 1042,
  "customer": {
    "id": 123456789,
    "phone": "+521234567890"
  },
  "total_price": "149.00",
  "currency": "MXN",
  "line_items": [
    {
      "id": 111111,
      "title": "Running Shoes",
      "quantity": 1,
      "price": "149.00",
      "product_id": 555555,
      "variant_id": 666666,
      "vendor": "NikeMX",
      "properties": []
    }
  ],
  "tags": "",
  "fulfillment_status": null,
  "financial_status": "paid",
  "created_at": "2025-01-15T11:00:00-05:00"
}

orders/cancelled Handler: ProcessShopifyOrderCancelledJob Same structure as orders/create with cancelled_at and cancel_reason fields added:
{
  "id": 987654321,
  "order_number": 1042,
  "customer": { "id": 123456789 },
  "total_price": "149.00",
  "cancelled_at": "2025-01-16T09:00:00-05:00",
  "cancel_reason": "customer"
}

orders/updated (used for shipping) Handler: ProcessShopifyOrderShippedJob
{
  "id": 987654321,
  "order_number": 1042,
  "customer": { "id": 123456789 },
  "fulfillment_status": "fulfilled",
  "fulfillments": [
    {
      "id": 222222,
      "status": "success",
      "tracking_company": "DHL",
      "tracking_number": "1234567890",
      "tracking_url": "https://track.dhl.com/...",
      "created_at": "2025-01-16T14:00:00-05:00"
    }
  ]
}
ProcessShopifyOrderShippedJob only fires OrderShipped when fulfillments is non-empty and contains at least one fulfillment with "status": "success". Other orders/updated events without fulfillment data are processed or ignored based on their content.

Product and collection webhooks

products/create Handler: ProcessShopifyProductCreatedJob
{
  "id": 555555,
  "title": "Running Shoes",
  "body_html": "<p>Full product description...</p>",
  "vendor": "NikeMX",
  "tags": "shoes, running, sport",
  "images": [
    { "id": 777777, "src": "https://cdn.shopify.com/...", "width": 1000, "height": 1000 }
  ],
  "variants": [
    {
      "id": 666666,
      "title": "Size 42 / Blue",
      "price": "149.00",
      "compare_at_price": "180.00",
      "sku": "RUN-42-BLU",
      "inventory_quantity": 15,
      "option1": "42",
      "option2": "Blue",
      "image_id": 777777
    }
  ],
  "options": [
    { "name": "Size", "values": ["40", "41", "42", "43"] },
    { "name": "Color", "values": ["Blue", "Black", "White"] }
  ],
  "status": "active",
  "created_at": "2025-01-15T09:00:00-05:00"
}

products/update Handler: ProcessShopifyProductUpdatedJob Same structure as products/create. Galantis processes the full payload — updated fields overwrite stored values, and inventory_quantity changes are checked for the 0→>0 Back-in-Stock restock pattern.
products/delete Handler: ProcessShopifyProductDeletedJob
{
  "id": 555555
}

collections/create, collections/update Handlers: ProcessShopifyCollectionCreatedJob, ProcessShopifyCollectionUpdatedJob
{
  "id": 888888,
  "title": "Running Gear",
  "handle": "running-gear",
  "products_count": 24,
  "updated_at": "2025-01-15T12:00:00-05:00"
}

collections/delete Handler: ProcessShopifyCollectionDeletedJob
{
  "id": 888888
}

Billing and app lifecycle webhooks

app_subscriptions/update Handler: MonitorBillingSubscriptionsJob
{
  "app_subscription": {
    "admin_graphql_api_id": "gid://shopify/AppSubscription/123",
    "name": "Galantis Pro Plan",
    "status": "ACTIVE",
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-15T00:00:00Z",
    "currency": "USD"
  }
}

app/uninstalled Handler: Tenant deactivation
{
  "id": 12345678,
  "myshopify_domain": "your-store.myshopify.com"
}

GDPR webhooks

customers/redact Handler: ProcessShopifyCustomersRedactJob
{
  "shop_id": 12345678,
  "shop_domain": "your-store.myshopify.com",
  "customer": {
    "id": 123456789,
    "email": "customer@example.com",
    "phone": "+521234567890"
  },
  "orders_to_redact": [987654321, 987654322]
}

shop/redact Handler: ProcessShopifyShopRedactJob
{
  "shop_id": 12345678,
  "shop_domain": "your-store.myshopify.com"
}

Meta webhooks

messages (inbound)
{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "{waba_id}",
    "changes": [{
      "value": {
        "messaging_product": "whatsapp",
        "metadata": {
          "display_phone_number": "521234567890",
          "phone_number_id": "{phone_number_id}"
        },
        "contacts": [{
          "profile": { "name": "Jane Smith" },
          "wa_id": "521234567890"
        }],
        "messages": [{
          "from": "521234567890",
          "id": "wamid.{message_id}",
          "timestamp": "1705320000",
          "type": "text",
          "text": { "body": "Hello, I have a question about my order" }
        }]
      },
      "field": "messages"
    }]
  }]
}
For QUICK_REPLY button responses, the messages[0].type is "interactive" and the payload includes:
"interactive": {
  "type": "button_reply",
  "button_reply": {
    "id": "{button_id}",
    "title": "{button_label}"
  }
}

message_status (status update)
{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "{waba_id}",
    "changes": [{
      "value": {
        "messaging_product": "whatsapp",
        "metadata": {
          "display_phone_number": "521234567890",
          "phone_number_id": "{phone_number_id}"
        },
        "statuses": [{
          "id": "wamid.{message_id}",
          "status": "delivered",
          "timestamp": "1705320030",
          "recipient_id": "521234567890"
        }]
      },
      "field": "messages"
    }]
  }]
}
"status" values: "sent", "delivered", "read", "played", "failed". For "failed" status, an "errors" array is included:
"errors": [{
  "code": 131047,
  "title": "Re-engagement message",
  "message": "Message failed to send because more than 24 hours have passed since the customer last replied to this number.",
  "error_data": { "details": "..." }
}]

message_template_status_update
{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "{waba_id}",
    "changes": [{
      "value": {
        "event": "APPROVED",
        "message_template_id": 123456,
        "message_template_name": "order_confirmation_es",
        "message_template_language": "es",
        "reason": null
      },
      "field": "message_template_status_update"
    }]
  }]
}
"event" values: "APPROVED", "REJECTED", "PAUSED", "DISABLED". For "REJECTED", the "reason" field contains Meta’s rejection explanation.