Overview

Firmhouse uses webhooks to allow you to communicate with different applications and share data smoothly. You can specify the information you want to send when each event happens using liquid templates. To set up a webhook on the Firmhouse Portal, check out this guide.

In this guide, we will use JSON payloads as it's the most common format for webhooks. However, you can use any other format that you can create a template for with Liquid, such as XML or YAML.

For each event group, there are specific variables that you can use in liquid templates.

Asset

You can use these variables in your templates for all asset events.

Asset assigned

This event is triggered when an asset is assigned to a customer. You can check out this guide to see how you can assign an asset to a customer on Firmhouse Portal.

Example Template
{
  "event": "asset_assigned",
  "asset": {
    "id": "{{asset.id}}",
    "productId": "{{asset.product.id}}",
    "internalNumber": "{{asset.internal_number}}",
    "externalNumber": "{{asset.external_number}}",
    "status": "{{asset.status}}",
    "purchasePrice": {{asset.purchase_price | default: 0}}
  },
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}"
  }
}

As shown in the example template above, you can use the liquid filter default: to set a default value for a field. You can also use any other filter supported by liquid. Check out the list here.


Contract term

You can use these variables in your templates for contract term events.

Billing cycle skipped

This event is triggered when a customer fails to pay for a billing cycle.

Example Template
{%- capture subscription_ordered_products_string -%}
  {%- for op in subscription.ordered_products -%}
    {
      "id": "{{op.id}}",
      "quantity": {{op.quantity}},
      "productId": "{{op.product.id}}",
      "price": "{{op.product.price_cents | default: 0}}",
      "sku": "{{op.product.sku}}"
    };
  {%- endfor -%}
{%- endcapture -%}
{% assign subscription_ordered_products = subscription_ordered_products_string | split:';' | join:"," %}
{
  "event": "billing_cycle_skipped",
  "subscribedPlan": {
    "id": {{subscribed_plan.id}},
    "activatedAt": "{{subscribed_plan.activated_at}}",
    "billingCycleInterval": "{{subscribed_plan.billing_cycle_interval}}",
    "billingCycleIntervalUnit": "{{subscribed_plan.billing_cycle_interval_unit}}",
    "fixedCommitmentEndsAt": "{{subscribed_plan.fixed_commitment_ends_at}}",
    "fixedCommitmentPeriod": "{{subscribed_plan.fixed_commitment_period}}",
    "fixedCommitmentUnit": "{{subscribed_plan.fixed_commitment_unit}}"
  },
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}",
    "paymentMethod": "{{subscription.payment_method}}",
    "currency": "{{subscription.currency}}",
    "monthlyAmountCents": "{{subscription.monthly_amount_cents}}",
    "orderedProducts": [{{subscription_ordered_products}}],
    "activePlan": {
      "id": "{{subscription.active_plan.id}}",
      "name": "{{subscription.active_plan.name}}"
    } 
  }
}

As you can see in the example above, you can use tags like capture and for .. in to extract values from arrays easily. You can also use other tags supported by liquid. You can check the full list here.


Collection Case

You can use these variables in your templates for extra field events.

Collection Case Closed

This event is triggered when the status of collection case is changed to closed.

Example Template
{%- capture invoice_items_string -%}
  {%- for invoice_item in invoices -%}
   {"id":"{{invoice_item.id}}", "number":"{{invoice_item.number}}", "amount": "{{invoice_item.amount}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign invoice_items = invoice_items_string | split:';' | join:"," %}
{
  "event": "collection_case_closed",
  "collection_case": {
    "id": "{{collection_case.id}}",
    "status": "{{collection_case.status}}",
    "created_at": "{{collection_case.created_at}}",
    "updated_at": "{{collection_case.updated_at}}",
    "case_number": "{{collection_case.case_number}}",
    "project_id": "{{collection_case.project_id}}",
    "case_type": "{{collection_case.case_type}}",
    "invoices": [{{invoice_items }}]
  },
  "subscription": {
    "id": "{{subscription.id}}"
  }
}

Collection Case Created

This event is triggered when a collection case is created for an invoice.

Example Template
{%- capture invoice_items_string -%}
  {%- for invoice_item in invoices -%}
   {"id":"{{invoice_item.id}}", "number":"{{invoice_item.number}}", "amount": "{{invoice_item.amount}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign invoice_items = invoice_items_string | split:';' | join:"," %}
{
  "event": "collection_case_created",
  "collection_case": {
    "id": "{{collection_case.id}}",
    "status": "{{collection_case.status}}",
    "created_at": "{{collection_case.created_at}}",
    "updated_at": "{{collection_case.updated_at}}",
    "case_number": "{{collection_case.case_number}}",
    "project_id": "{{collection_case.project_id}}",
    "case_type": "{{collection_case.case_type}}",
    "invoices": [{{invoice_items }}]
  },
  "subscription": {
    "id": "{{subscription.id}}"
  }
}

Collection Case Open

This event is triggered when the status of collection case is changed to open.

Example Template
{%- capture invoice_items_string -%}
  {%- for invoice_item in invoices -%}
   {"id":"{{invoice_item.id}}", "number":"{{invoice_item.number}}", "amount": "{{invoice_item.amount}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign invoice_items = invoice_items_string | split:';' | join:"," %}
{
  "event": "collection_case_open",
  "collection_case": {
    "id": "{{collection_case.id}}",
    "status": "{{collection_case.status}}",
    "created_at": "{{collection_case.created_at}}",
    "updated_at": "{{collection_case.updated_at}}",
    "case_number": "{{collection_case.case_number}}",
    "project_id": "{{collection_case.project_id}}",
    "case_type": "{{collection_case.case_type}}",
    "invoices": [{{invoice_items }}]
  },
  "subscription": {
    "id": "{{subscription.id}}"
  }
}

Extra field answer

If you added extra fields to your project, you can use these events to monitor when they are changed. Please check out this guide for instructions on setting up extra fields on Firmhouse Portal.

You can use these variables in your templates for extra field events.

  • extra_field

    • This field contains all extra_fields you configured for the project. You can access each with `{{extra_field.field_name}}. The field names here are using snake_case. If you have an extra field with the name "Custom Message", you can access that with {{extra_field.custom_message}} tag.

Extra field answer updated

This event is triggered when one of the extra fields you defined for your project is updated on a subscription.

Example Template
{
  "event": "extra_field_answer_updated",
  "extra_field": {
    "how_did_you_hear_about_us": "{{extra_field.how_did_you_hear_about_us}}",
    "custom_message": "{{extra_field.custom_message}}"
  },
  "subscription": {
    "id": "{{subscription.id}}"
  }
}

Invoice

You can use these variables in your templates for all invoice events.

Invoice invoiced

This event is triggered when an invoice is created.

Example Template
{%- capture invoice_line_items_string -%}
  {%- for invoice_line_item in invoice.invoice_line_items -%}
   {"description": "{{invoice_line_item.description}}", "id":"{{invoice_line_item.id}}","quantity": {{invoice_line_item.quantity}}, "totalAmountIncludingTaxCents": {{invoice_line_item.total_amount_including_tax_cents}}, "lineItemType": "{{invoice_line_item.line_item_type}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign invoice_line_items = invoice_line_items_string | split:';' | join:"," %}
{
  "event": "invoice_invoiced",
  "subscription": {
    "id": "{{subscription.id}}"
  },
  "invoice": {
    "amountPriceCents": {{invoice.amount_price_cents}},
    "currency": "{{invoice.currency}}",
    "statusCode": "{{invoice.status_code}}",
    "status": "{{invoice.status}}",
    "invoiceLineItems": [{{invoice_line_items}}]
  }
}

Invoice paid

This event is triggered when the payment for an invoice is paid successfully.

Example Template
{%- capture invoice_line_items_string -%}
  {%- for invoice_line_item in invoice.invoice_line_items -%}
   {"description": "{{invoice_line_item.description}}", "id":"{{invoice_line_item.id}}","quantity": {{invoice_line_item.quantity}}, "totalAmountIncludingTaxCents": {{invoice_line_item.total_amount_including_tax_cents}}, "lineItemType": "{{invoice_line_item.line_item_type}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign invoice_line_items = invoice_line_items_string | split:';' | join:"," %}
{
  "event": "invoice_paid",
  "subscription": {
    "id": "{{subscription.id}}"
  },
  "invoice": {
    "amountPriceCents": {{invoice.amount_price_cents}},
    "currency": "{{invoice.currency}}",
    "statusCode": "{{invoice.status_code}}",
    "status": "{{invoice.status}}",
    "invoiceLineItems": [{{invoice_line_items}}]
  },
  "payment": {
    "id": "{{payment.payment_id}}",
    "attemptsCount": {{payment.attempts_count}},
    "description": "{{payment.description}}",
    "payment_type": "{{payment.payment_type}}",
    "status": "{{payment.status}}"
  }
}


Order

You can use these variables in your templates for all order events.

Order confirmed

This event is triggered when an order gets confirmed.

Example Template
{%- capture order_line_items_string -%}
  {%- for order_line_item in invoice.invoice_line_items -%}
   {"productTitle": "{{order_line_item.product.title}}", "productId":"{{order_line_item.product.id}}","quantity": {{order_line_item.quantity}}, "metadata": "{{order_line_item.metadata}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign order_line_items = order_line_items_string | split:';' | join:"," %}
{
  "event": "order_confirmed",
  "order": {
    "id": "{{order.id}}",
    "amountCents": {{order.amount_cents | default: 0}},
    "ammountCurrency": "{{order.amount_currency}}",
    "orderLines": [{{order_line_items}}],
    "shippingCostCents": {{order.shipping_cost_cents | default: 0}},
    "shippingCostsCurrency": "{{order.shipping_costs_currency}}",
    "discountCents": {{order.discount_cents | default: 0}},
    "discountCurrency": "{{order.discount_currency}}",
    "state": "{{order.state}}",
    "status": "{{order.status}}"
  },
  "subscription": {
    "id": "{{subscription.id}}"
  }
}


Order fulfilled

This event is triggered when an order status becomes fulfilled.

Example Template
{%- capture order_line_items_string -%}
  {%- for order_line_item in invoice.invoice_line_items -%}
   {"productTitle": "{{order_line_item.product.title}}", "productId":"{{order_line_item.product.id}}","quantity": {{order_line_item.quantity}}, "metadata": "{{order_line_item.metadata}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign order_line_items = order_line_items_string | split:';' | join:"," %}
{
  "event": "order_fulfilled",
  "order": {
    "id": "{{order.id}}",
    "amountCents": {{order.amount_cents | default: 0}},
    "ammountCurrency": "{{order.amount_currency}}",
    "orderLines": [{{order_line_items}}],
    "shippingCostCents": {{order.shipping_cost_cents | default: 0}},
    "shippingCostsCurrency": "{{order.shipping_costs_currency}}",
    "discountCents": {{order.discount_cents | default: 0}},
    "discountCurrency": "{{order.discount_currency}}",
    "state": "{{order.state}}",
    "status": "{{order.status}}"
  },
  "subscription": {
    "id": "{{subscription.id}}"
  }
}

Order pending

This event is triggered when an order status changes to pending.

Example Template
{%- capture order_line_items_string -%}
  {%- for order_line_item in invoice.invoice_line_items -%}
   {"productTitle": "{{order_line_item.product.title}}", "productId":"{{order_line_item.product.id}}","quantity": {{order_line_item.quantity}}, "metadata": "{{order_line_item.metadata}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign order_line_items = order_line_items_string | split:';' | join:"," %}
{
  "event": "order_pending",
  "order": {
    "id": "{{order.id}}",
    "amountCents": {{order.amount_cents | default: 0}},
    "ammountCurrency": "{{order.amount_currency}}",
    "orderLines": [{{order_line_items}}],
    "shippingCostCents": {{order.shipping_cost_cents | default: 0}},
    "shippingCostsCurrency": "{{order.shipping_costs_currency}}",
    "discountCents": {{order.discount_cents | default: 0}},
    "discountCurrency": "{{order.discount_currency}}",
    "state": "{{order.state}}",
    "status": "{{order.status}}"
  },
  "subscription": {
    "id": "{{subscription.id}}"
  }
}


Ordered product

You can use these variables in your templates for all ordered product events.

Ordered product created

This event is triggered when a customer adds a new product to cart. This corresponds to createOrderedProduct mutation on our GraphQL API. Note that if the same product added more than one times, since it's only a quantity update, Ordered product updated event will be triggered.

Example Template
{%- capture subscription_ordered_products_string -%}
  {%- for op in subscription.ordered_products -%}
    {
      "id": "{{op.id}}",
      "quantity": {{op.quantity}},
      "productId": "{{op.product.id}}",
      "price": "{{op.product.price_cents | default: 0}}",
      "sku": "{{op.product.sku}}"
    };
  {%- endfor -%}
{%- endcapture -%}
{% assign subscription_ordered_products = subscription_ordered_products_string | split:';' | join:"," %}
{
  "event": "ordered_product_created",
  "orderedProduct": {
    "id": {{ordered_product.id}},
    "product": {
      "id": "{{ordered_product.product.id}}",
      "price": "{{ordered_product.product.price_cents | default: 0}}",
      "sku": "{{ordered_product.product.sku}}"
    },
    "quantity": {{ordered_product.quantity}}
  },
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}",
    "paymentMethod": "{{subscription.payment_method}}",
    "currency": "{{subscription.currency}}",
    "monthlyAmountCents": "{{subscription.monthly_amount_cents}}",
    "orderedProducts": [{{subscription_ordered_products}}],
    "activePlan": {
      "id": "{{subscription.active_plan.id}}",
      "name": "{{subscription.active_plan.name}}"
    } 
  }
}

Ordered product updated

This event is triggered when a product in cart is updated. This corresponds to updateOrderedProduct and updateOrderedProductQuantity mutations on our GraphQL API or when its automatically updated due to order state or shipment information change.

Example Template
{%- capture subscription_ordered_products_string -%}
  {%- for op in subscription.ordered_products -%}
    {
      "id": "{{op.id}}",
      "quantity": {{op.quantity}},
      "productId": "{{op.product.id}}",
      "price": "{{op.product.price_cents | default: 0}}",
      "sku": "{{op.product.sku}}"
    };
  {%- endfor -%}
{%- endcapture -%}
{% assign subscription_ordered_products = subscription_ordered_products_string | split:';' | join:"," %}
{
  "event": "ordered_product_updated",
  "orderedProduct": {
    "id": {{ordered_product.id}},
    "product": {
      "id": "{{ordered_product.product.id}}",
      "price": "{{ordered_product.product.price_cents | default: 0}}",
      "sku": "{{ordered_product.product.sku}}"
    },
    "quantity": {{ordered_product.quantity}}
  },
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}",
    "paymentMethod": "{{subscription.payment_method}}",
    "currency": "{{subscription.currency}}",
    "monthlyAmountCents": "{{subscription.monthly_amount_cents}}",
    "orderedProducts": [{{subscription_ordered_products}}],
    "activePlan": {
      "id": "{{subscription.active_plan.id}}",
      "name": "{{subscription.active_plan.name}}"
    } 
  }
}

Ordered product deleted

This event is triggered when a customer removed product from a cart. This corresponds to destroyOrderedProduct mutation on our GraphQL API. ordered_product variable in this even corresponds to the product removed from cart

Example Template
{%- capture subscription_ordered_products_string -%}
  {%- for op in subscription.ordered_products -%}
    {
      "id": "{{op.id}}",
      "quantity": {{op.quantity}},
      "productId": "{{op.product.id}}",
      "price": "{{op.product.price_cents | default: 0}}",
      "sku": "{{op.product.sku}}"
    };
  {%- endfor -%}
{%- endcapture -%}
{% assign subscription_ordered_products = subscription_ordered_products_string | split:';' | join:"," %}
{
  "event": "ordered_product_deleted",
  "orderedProduct": {
    "id": {{ordered_product.id}},
    "product": {
      "id": "{{ordered_product.product.id}}",
      "price": "{{ordered_product.product.price_cents | default: 0}}",
      "sku": "{{ordered_product.product.sku}}"
    },
    "quantity": {{ordered_product.quantity}}
  },
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}",
    "paymentMethod": "{{subscription.payment_method}}",
    "currency": "{{subscription.currency}}",
    "monthlyAmountCents": "{{subscription.monthly_amount_cents}}",
    "orderedProducts": [{{subscription_ordered_products}}],
    "activePlan": {
      "id": "{{subscription.active_plan.id}}",
      "name": "{{subscription.active_plan.name}}"
    } 
  }
}

Payment

You can use these variables in your templates for all payment events.

Payment failed

This event is triggered when a payment is failed.

Example Template
{%- capture invoice_line_items_string -%}
  {%- for invoice_line_item in invoice.invoice_line_items -%}
   {"description": "{{invoice_line_item.description}}", "id":"{{invoice_line_item.id}}","quantity": {{invoice_line_item.quantity}}, "totalAmountIncludingTaxCents": {{invoice_line_item.total_amount_including_tax_cents}}, "lineItemType": "{{invoice_line_item.line_item_type}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign invoice_line_items = invoice_line_items_string | split:';' | join:"," %}
{
  "event": "payment_failed",
  "subscription": {
    "id": "{{subscription.id}}"
  },
  "invoice": {
    "amountPriceCents": {{invoice.amount_price_cents}},
    "currency": "{{invoice.currency}}",
    "statusCode": "{{invoice.status_code}}",
    "status": "{{invoice.status}}",
    "invoiceLineItems": [{{invoice_line_items}}]
  },
  "payment": {
    "id": "{{payment.payment_id}}",
    "attemptsCount": {{payment.attempts_count}},
    "description": "{{payment.description}}",
    "payment_type": "{{payment.payment_type}}",
    "status": "{{payment.status}}",
    "scheduledRetryOn": "{{payment.scheduled_retry_on}}",
    "payNowUrl": "{{payment.pay_now_url}}",
    "failureReason": "{{payment.failure_reason}}"
  }
}

Payment refunded

This event is triggered when a payment is refunded.

Example Template
{%- capture invoice_line_items_string -%}
  {%- for invoice_line_item in invoice.invoice_line_items -%}
   {"description": "{{invoice_line_item.description}}", "id":"{{invoice_line_item.id}}","quantity": {{invoice_line_item.quantity}}, "totalAmountIncludingTaxCents": {{invoice_line_item.total_amount_including_tax_cents}}, "lineItemType": "{{invoice_line_item.line_item_type}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign invoice_line_items = invoice_line_items_string | split:';' | join:"," %}
{
  "event": "payment_refunded",
  "subscription": {
    "id": "{{subscription.id}}"
  },
  "invoice": {
    "amountPriceCents": {{invoice.amount_price_cents}},
    "currency": "{{invoice.currency}}",
    "statusCode": "{{invoice.status_code}}",
    "status": "{{invoice.status}}",
    "invoiceLineItems": [{{invoice_line_items}}]
  },
  "payment": {
    "id": "{{payment.payment_id}}",
    "attemptsCount": {{payment.attempts_count}},
    "description": "{{payment.description}}",
    "payment_type": "{{payment.payment_type}}",
    "status": "{{payment.status}}",
    "scheduledRetryOn": "{{payment.scheduled_retry_on}}",
    "payNowUrl": "{{payment.pay_now_url}}",
    "failureReason": "{{payment.failure_reason}}"
  }
}

Payment succeeded

This event is triggered when a payment successfully completes.

Example Template
{%- capture invoice_line_items_string -%}
  {%- for invoice_line_item in invoice.invoice_line_items -%}
   {"description": "{{invoice_line_item.description}}", "id":"{{invoice_line_item.id}}","quantity": {{invoice_line_item.quantity}}, "totalAmountIncludingTaxCents": {{invoice_line_item.total_amount_including_tax_cents}}, "lineItemType": "{{invoice_line_item.line_item_type}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign invoice_line_items = invoice_line_items_string | split:';' | join:"," %}
{
  "event": "payment_succeeded",
  "subscription": {
    "id": "{{subscription.id}}"
  },
  "invoice": {
    "amountPriceCents": {{invoice.amount_price_cents}},
    "currency": "{{invoice.currency}}",
    "statusCode": "{{invoice.status_code}}",
    "status": "{{invoice.status}}",
    "invoiceLineItems": [{{invoice_line_items}}]
  },
  "payment": {
    "id": "{{payment.payment_id}}",
    "attemptsCount": {{payment.attempts_count}},
    "description": "{{payment.description}}",
    "payment_type": "{{payment.payment_type}}",
    "status": "{{payment.status}}"
  }
}

Return order

You can use these variables in your templates for all return order events.

Return order cancelled

This event is triggered when a return order is cancelled.

Example Template
{%- capture return_order_products_string -%}
  {%- for item in return_order.return_order_products -%}
   {"quantity": {{item.quantity}}, "orderedProductId": "{{item.ordered_product.id}}", "productId": "{{item.ordered_product.product_id}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign return_order_products = return_order_products_string | split:';' | join:"," %}
{
  "event": "return_order_cancelled",
  "subscription": {
    "id": "{{subscription.id}}"
  },
  "returnOrder": {
    "id": "{{return_order.id}}",
    "reason": "{{return_order.reason}}",
    "desiredReturnDate": "{{return_order.desired_return_date}}",
    "status": "{{return_order.status}}",
    "trackingCode": "{{return_order.tracking_code}}",
    "trackingUrl": "{{return_order.tracking_url}}",
    "externalStatus": "{{return_order.external_status}}",
    "externalReferance": "{{return_order.external_referance}}",
    "externalUrl": "{{return_order.external_url}}",
    "returnLabelFileUrl": "{{return_order.return_label_file_url}}",
    "returnedOn": "{{return_order.returned_on}}",
    "returnOrderProducts": [{{return_order_products}}]
  }
}

Return order completed

This event is triggered when a return order is completed.

Example Template
{%- capture return_order_products_string -%}
  {%- for item in return_order.return_order_products -%}
   {"quantity": {{item.quantity}}, "orderedProductId": "{{item.ordered_product.id}}", "productId": "{{item.ordered_product.product_id}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign return_order_products = return_order_products_string | split:';' | join:"," %}
{
  "event": "return_order_completed",
  "subscription": {
    "id": "{{subscription.id}}"
  },
  "returnOrder": {
    "id": "{{return_order.id}}",
    "reason": "{{return_order.reason}}",
    "desiredReturnDate": "{{return_order.desired_return_date}}",
    "status": "{{return_order.status}}",
    "trackingCode": "{{return_order.tracking_code}}",
    "trackingUrl": "{{return_order.tracking_url}}",
    "externalStatus": "{{return_order.external_status}}",
    "externalReferance": "{{return_order.external_referance}}",
    "externalUrl": "{{return_order.external_url}}",
    "returnLabelFileUrl": "{{return_order.return_label_file_url}}",
    "returnedOn": "{{return_order.returned_on}}",
    "returnOrderProducts": [{{return_order_products}}]
  }
}
liq

Return order created

This event is triggered when a return order is created.

Example Template
{%- capture return_order_products_string -%}
  {%- for item in return_order.return_order_products -%}
   {"quantity": {{item.quantity}}, "orderedProductId": "{{item.ordered_product.id}}", "productId": "{{item.ordered_product.product_id}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign return_order_products = return_order_products_string | split:';' | join:"," %}
{
  "event": "return_order_created",
  "subscription": {
    "id": "{{subscription.id}}"
  },
  "returnOrder": {
    "id": "{{return_order.id}}",
    "reason": "{{return_order.reason}}",
    "desiredReturnDate": "{{return_order.desired_return_date}}",
    "status": "{{return_order.status}}",
    "trackingCode": "{{return_order.tracking_code}}",
    "trackingUrl": "{{return_order.tracking_url}}",
    "externalStatus": "{{return_order.external_status}}",
    "externalReferance": "{{return_order.external_referance}}",
    "externalUrl": "{{return_order.external_url}}",
    "returnLabelFileUrl": "{{return_order.return_label_file_url}}",
    "returnedOn": "{{return_order.returned_on}}",
    "returnOrderProducts": [{{return_order_products}}]
  }
}

Subscription acceptance check

If you are using manual activation, you can use these events to track the status of acceptance checks. Please refer to this guide for setting up manual activation and acceptance checks.

If you are using duplication, or Focum acceptance check with "As part of the signup on submitting the signup form" option, the acceptance check will be created and validated during sign up. This corresponds to createSubscriptionFromCart call.

For other types of acceptance checks, namely Manual, Identity Verification or Focum acceptance check with "As part of the signup on submitting the signup form." option, the acceptance check will be created after customer completes the payment with pending status.

You can use these variables in your templates for all subscription acceptance check events.

Subscription acceptance check created

This event is triggered when an acceptance check is created for a subscription.

Example template
{%- capture acceptance_checks_string -%}
  {%- for check in subscription.subscription_acceptance_checks -%}
   {"name": "{{check.name}}", "id":"{{check.id}}","status": "{{check.status}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign acceptance_checks = acceptance_checks_string | split:';' | join:"," %}

{
  "event": "subscription_acceptance_check_created",
  "subscription_acceptance_checks": [{{acceptance_checks}}],
  "subscription": {
    "id": "{{subscription.id}}"
  }
}

Subscription acceptance check pending

This event is triggered when an acceptance check is created with pending status. It will only be triggered for these acceptance check types: Manual, Identity Verification, Focum acceptance check with "As part of the signup on submitting the signup form."

Example template
{%- capture acceptance_checks_string -%}
  {%- for check in subscription.subscription_acceptance_checks -%}
   {"name": "{{check.name}}", "id":"{{check.id}}","status": "{{check.status}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign acceptance_checks = acceptance_checks_string | split:';' | join:"," %}

{
  "event": "subscription_acceptance_check_pending",
  "subscription_acceptance_checks": [{{acceptance_checks}}],
  "subscription": {
    "id": "{{subscription.id}}"
  }
}

Subscription acceptance check accepted

This event is triggered when the status of an acceptance check changes to accepted.

This will happen immediately on signup if the check passes when its created for these events: duplication, or Focum acceptance check with "As part of the signup on submitting the signup form" option. For other acceptance check types it will happen when the value is set to accepted.

Example template
{%- capture acceptance_checks_string -%}
  {%- for check in subscription.subscription_acceptance_checks -%}
   {"name": "{{check.name}}", "id":"{{check.id}}","status": "{{check.status}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign acceptance_checks = acceptance_checks_string | split:';' | join:"," %}

{
  "event": "subscription_acceptance_check_accepted",
  "subscription_acceptance_checks": [{{acceptance_checks}}],
  "subscription": {
    "id": "{{subscription.id}}"
  }
}

Subscription acceptance check rejected

This event is triggered when the status of an acceptance check changes to rejected.

The triggering timeline is similar to Subscription acceptance check accepted. The only difference is that it occurs when the checks fail or when it is manually set to rejected.

Example template
{%- capture acceptance_checks_string -%}
  {%- for check in subscription.subscription_acceptance_checks -%}
   {"name": "{{check.name}}", "id":"{{check.id}}","status": "{{check.status}}"};
  {%- endfor -%}
{%- endcapture -%}
{% assign acceptance_checks = acceptance_checks_string | split:';' | join:"," %}


{
  "event": "subscription_acceptance_check_rejected",
  "subscription_acceptance_checks": [{{acceptance_checks}}],
  "subscription": {
    "id": "{{subscription.id}}"
  }
}

Subscription

You can use these variables in your templates for all subscription events.

Subscription activated

This event is triggered when a subscription is activated. Depending on your project settings this could happen either after successful initial payment or when the subscription is manually activated.

Example Template
{%- capture subscription_ordered_products_string -%}
  {%- for op in subscription.ordered_products -%}
    {
      "id": "{{op.id}}",
      "quantity": {{op.quantity}},
      "productId": "{{op.product.id}}",
      "price": "{{op.product.price_cents | default: 0}}",
      "sku": "{{op.product.sku}}"
    };
  {%- endfor -%}
{%- endcapture -%}
{% assign subscription_ordered_products = subscription_ordered_products_string | split:';' | join:"," %}
{
  "event": "subscription_activated",
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}",
    "paymentMethod": "{{subscription.payment_method}}",
    "currency": "{{subscription.currency}}",
    "monthlyAmountCents": "{{subscription.monthly_amount_cents}}",
    "orderedProducts": [{{subscription_ordered_products}}],
    "activePlan": {
      "id": "{{subscription.active_plan.id}}",
      "name": "{{subscription.active_plan.name}}"
    } 
  }
}

Subscription address changed

This event is triggered when subscription details are updated. Note that, updates to subscriptions with draft status won't trigger this event.

Example Template
{%- capture subscription_ordered_products_string -%}
  {%- for op in subscription.ordered_products -%}
    {
      "id": "{{op.id}}",
      "quantity": {{op.quantity}},
      "productId": "{{op.product.id}}",
      "price": "{{op.product.price_cents | default: 0}}",
      "sku": "{{op.product.sku}}"
    };
  {%- endfor -%}
{%- endcapture -%}
{% assign subscription_ordered_products = subscription_ordered_products_string | split:';' | join:"," %}
{
  "event": "subscription_address_changed",
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}",
    "paymentMethod": "{{subscription.payment_method}}",
    "currency": "{{subscription.currency}}",
    "monthlyAmountCents": "{{subscription.monthly_amount_cents}}",
    "orderedProducts": [{{subscription_ordered_products}}],
    "activePlan": {
      "id": "{{subscription.active_plan.id}}",
      "name": "{{subscription.active_plan.name}}"
    } 
  }
}

Subscription cancellation confirmation

This event triggers when a subscription is actually cancelled. If you enabled two step cancellation on your project, this corresponds to when you confirm cancellation through firmhoues portal. To learn more about two step cancellation, please refer to this guide.

If two step cancellation is disabled, it will be directly triggered after Subscription cancellation initiation event

Example Template
{%- capture subscription_ordered_products_string -%}
  {%- for op in subscription.ordered_products -%}
    {
      "id": "{{op.id}}",
      "quantity": {{op.quantity}},
      "productId": "{{op.product.id}}",
      "price": "{{op.product.price_cents | default: 0}}",
      "sku": "{{op.product.sku}}"
    };
  {%- endfor -%}
{%- endcapture -%}
{% assign subscription_ordered_products = subscription_ordered_products_string | split:';' | join:"," %}
{
  "event": "subscription_cancellation_confirmation",
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}",
    "paymentMethod": "{{subscription.payment_method}}",
    "currency": "{{subscription.currency}}",
    "monthlyAmountCents": "{{subscription.monthly_amount_cents}}",
    "orderedProducts": [{{subscription_ordered_products}}],
    "activePlan": {
      "id": "{{subscription.active_plan.id}}",
      "name": "{{subscription.active_plan.name}}"
    } 
  }
}

Subscription cancellation initiation

This event is triggered when a cancellation request is submitted.

Example Template
{%- capture subscription_ordered_products_string -%}
  {%- for op in subscription.ordered_products -%}
    {
      "id": "{{op.id}}",
      "quantity": {{op.quantity}},
      "productId": "{{op.product.id}}",
      "price": "{{op.product.price_cents | default: 0}}",
      "sku": "{{op.product.sku}}"
    };
  {%- endfor -%}
{%- endcapture -%}
{% assign subscription_ordered_products = subscription_ordered_products_string | split:';' | join:"," %}
{
  "event": "subscription_cancellation_initiation",
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}",
    "paymentMethod": "{{subscription.payment_method}}",
    "currency": "{{subscription.currency}}",
    "monthlyAmountCents": "{{subscription.monthly_amount_cents}}",
    "orderedProducts": [{{subscription_ordered_products}}],
    "activePlan": {
      "id": "{{subscription.active_plan.id}}",
      "name": "{{subscription.active_plan.name}}"
    } 
  }
}


Subscription signed up

This event is triggered when customer signs up. This corresponds to customer completing the initial payment successfully.

Example Template
{%- capture subscription_ordered_products_string -%}
  {%- for op in subscription.ordered_products -%}
    {
      "id": "{{op.id}}",
      "quantity": {{op.quantity}},
      "productId": "{{op.product.id}}",
      "price": "{{op.product.price_cents | default: 0}}",
      "sku": "{{op.product.sku}}"
    };
  {%- endfor -%}
{%- endcapture -%}
{% assign subscription_ordered_products = subscription_ordered_products_string | split:';' | join:"," %}
{
  "event": "subscription_signed_up",
  "subscription": {
    "id": "{{subscription.id}}",
    "email": "{{subscription.email}}",
    "name": "{{subscription.name}}",
    "lastName": "{{subscription.last_name}}",
    "phoneNumber": "{{subscription.phone_number}}",
    "address": "{{subscription.address}}",
    "houseNumber": "{{subscription.house_number}}",
    "city": "{{subscription.city}}",
    "state": "{{subscription.state}}",
    "zipcode": "{{subscription.zipcode}}",
    "country": "{{subscription.country}}",
    "paymentMethod": "{{subscription.payment_method}}",
    "currency": "{{subscription.currency}}",
    "monthlyAmountCents": "{{subscription.monthly_amount_cents}}",
    "orderedProducts": [{{subscription_ordered_products}}],
    "activePlan": {
      "id": "{{subscription.active_plan.id}}",
      "name": "{{subscription.active_plan.name}}"
    } 
  }
}


Last updated