Information in a Moneybird account is constantly changing. If you want to perform actions based on these changes, webhooks help you to achieve this. Instead of querying the API at a certain interval, Moneybird will notify you about changes to information in the bookkeeping.

Usage

Webhooks are useful in a broad range of situations. When the state of a sales invoice changes, Moneybird will perform an HTTP request to the URL you provide. Based on the payload of the request, you can determine which action you need to perform.

How it works:

  • You need a URL that Moneybird can call to deliver the payload. The Moneybird servers must be able to access this URL.
  • You can add HTTP basic authentication or other token authentication in the URL, as long as the URL stays valid.
  • Your URL always needs to respond with a 200 HTTP status. Upon registration this is checked.
  • When your URL responds with another HTTP status code, Moneybird will retry to deliver the push 10 times. The time interval between retries is gradually extended.
  • After each push, Moneybird will store the last HTTP status code and HTTP body. Using the webhooks API, you can retrieve this information for debugging purposes.

You can register as many webhooks as required in an administration. Registration is done by sending a POST request to the webhooks API.

We strongly recommend that you use a secure HTTPS endpoint for receiving payload from Moneybird.
If you use unencrypted HTTP, anyone on the network may be able to listen in on sensitive information like contacts and invoices.

Events

It is also possible to subscribe to events. When an event you are subscribed to occurs, Moneybird will perform an HTTP request to the URL you provide. The following events are available:

contact_changed
contact_created
contact_merged
credit_invoice_created_from_original
default_identity_updated
default_tax_rate_created
direct_bank_link_activated
document_attachment_skipped
document_destroyed
document_expired
document_recurred
document_saved
document_saved_from_email
document_saved_from_endpoint
document_saved_from_si
document_saved_from_upload
document_style_created
document_style_destroyed
document_style_updated
document_updated
estimate_accepted_contact
estimate_billed
estimate_created
estimate_created_from_original
estimate_destroyed
estimate_mark_accepted
estimate_mark_archived
estimate_mark_billed
estimate_mark_late
estimate_mark_open
estimate_mark_rejected
estimate_send_email
estimate_send_manually
estimate_send_post
estimate_send_post_cancelled
estimate_send_post_confirmation
estimate_signed_sender
estimate_state_changed_to_late
estimate_updated
financial_account_activated
financial_account_created
financial_account_deactivated
financial_account_destroyed
financial_account_renamed
financial_statement_created
financial_statement_destroyed
financial_statement_updated
identity_created
identity_destroyed
identity_updated
ledger_account_activated
ledger_account_booking_created
ledger_account_booking_destroyed
ledger_account_created
ledger_account_deactivated
ledger_account_destroyed
ledger_account_updated
note_created
note_destroyed
payment_destroyed
payment_linked_to_financial_mutation
payment_registered
payment_send_email
payment_transaction_batch_cancelled
payment_transaction_batch_created
recurring_sales_invoice_auto_send_forcefully_disabled
recurring_sales_invoice_created
recurring_sales_invoice_created_from_original
recurring_sales_invoice_created_from_original_recurring
recurring_sales_invoice_creating_skipped_due_to_limits
recurring_sales_invoice_deactivated
recurring_sales_invoice_destroyed
recurring_sales_invoice_invoice_created
recurring_sales_invoice_started_auto_send
recurring_sales_invoice_stopped_auto_send
recurring_sales_invoice_updated
sales_invoice_created
sales_invoice_created_based_on_estimate
sales_invoice_created_based_on_recurring
sales_invoice_created_from_original
sales_invoice_destroyed
sales_invoice_marked_as_uncollectible
sales_invoice_merged
sales_invoice_merged_with_recurring_sales_invoice
sales_invoice_paused
sales_invoice_send_email
sales_invoice_send_manually
sales_invoice_send_post
sales_invoice_send_post_confirmation
sales_invoice_send_post_cancelled
sales_invoice_send_reminder_email
sales_invoice_send_reminder_manually
sales_invoice_send_reminder_post
sales_invoice_send_reminder_post_confirmation
sales_invoice_send_si
sales_invoice_send_si_delivered
sales_invoice_send_si_error
sales_invoice_send_to_payt
sales_invoice_state_changed_to_draft
sales_invoice_state_changed_to_late
sales_invoice_state_changed_to_open
sales_invoice_state_changed_to_paid
sales_invoice_state_changed_to_pending_payment
sales_invoice_state_changed_to_reminded
sales_invoice_state_changed_to_scheduled
sales_invoice_unpaused
sales_invoice_updated
send_payment_email
tax_rate_activated
tax_rate_created
tax_rate_deactivated
tax_rate_destroyed
tax_rate_updated
todo_completed
todo_created
todo_destroyed
todo_opened
workflow_created
workflow_deactivated
workflow_destroyed
workflow_updated
If you decide to not subscribe to any events the old implementation will be used (notifications after state changes of sales invoices). This is to prevent existing webhooks from failing. If you would like to subscribe to a group of events, you can use the top level name of the event (eg. estimate).

Payload

The URL in a webhook will be called by using a `POST` HTTP request. The HTTP body contains a JSON payload with the following structure:

{
  "administration_id": "116015326147118082",
  "webhook_id": "116010948233266179",
  "entity_type": "SalesInvoice",
  "entity_id": "116015245643744263",
  "state": "late",
  "action": "sales_invoice_state_changed_to_late",
  "entity": {
    "id": "116015245643744263",
    "contact_id": "116015245567198212",
    "contact": {
      "id": "116015245567198212",
      "company_name": "Foobar Holding B.V.",
      "firstname": "",
      "lastname": "",
      "attention": "",
      "address1": "Hoofdstraat 12",
      "address2": "",
      "zipcode": "1234AB",
      "city": "Amsterdam",
      "country": "NL",
      "email": "info@example.com",
      "phone": "",
      "send_method": "email",
      "customer_id": "1",
      "tax_number": "",
      "chamber_of_commerce": "",
      "bank_account": "",
      "send_invoices_to_attention": "",
      "send_invoices_to_email": "info@example.com",
      "send_estimates_to_attention": "",
      "send_estimates_to_email": "info@example.com",
      "sepa_active": false,
      "sepa_iban": "",
      "sepa_bic": "",
      "sepa_mandate_id": "",
      "sepa_mandate_date": null,
      "created_at": "2015-02-25T10:39:41.615Z",
      "updated_at": "2015-02-25T10:39:41.615Z",
      "notes": [

      ],
      "custom_fields": [

      ]
    },
    "invoice_id": null,
    "workflow_id": "116015053116802148",
    "document_style_id": "116015053175522406",
    "state": "late",
    "invoice_date": null,
    "payment_conditions": "We verzoeken u vriendelijk het bovenstaande bedrag van {document.total_price} voor {document.due_date} te voldoen op onze bankrekening onder vermelding van het factuurnummer {document.invoice_id}. Voor vragen kunt u contact opnemen per e-mail.",
    "reference": "Project X",
    "language": "nl",
    "currency": "EUR",
    "discount": "0.0",
    "paid_at": null,
    "sent_at": null,
    "created_at": "2015-02-25T10:39:41.685Z",
    "updated_at": "2015-02-25T10:39:41.685Z",
    "details": [
      {
        "id": "116015245648987144",
        "tax_rate_id": "116015052994118749",
        "ledger_account_id": "116015052938544219",
        "amount": "1 x",
        "description": "Project X",
        "price": "300.0",
        "row_order": 1,
        "total_price_excl_tax_with_discount": "300.0",
        "total_price_excl_tax_with_discount_base": "300.0",
        "tax_report_reference": [
          "NL/1a"
        ],
        "created_at": "2015-02-25T10:39:41.693Z",
        "updated_at": "2015-02-25T10:39:41.693Z"
      }
    ],
    "payments": [

    ],
    "custom_fields": [

    ],
    "notes": [

    ],
    "attachments": [

    ]
  }
}

The entity attribute contains a representation of the entity equal to the JSON representation you get when requesting the entity using the API. The state attribute contains the new state of the entity that triggered the push. Notice that the state in the push and the state in the entity can differ. The state of the entity could have changed in the meantime and always contains the current state in the database. The action attribute contains the name of the event that triggered the push.