# Service Lifecycle Hooks

https://dev.wisecp.com/es/service-lifecycle-hooks

The 97 hooks opened across a sold service's life: setting up, suspending, cancelling, renewing, changing plan, and talking to the provider module.

## Overview

A service is the thing a customer bought: a hosting package, a server, a software licence. The hooks here follow its **life**. Most come in pairs: a gate in front of an action and an event behind it.

Another part is about the **module** actually providing the service. The code opening an account on a server, suspending it or changing a password lives there. These hooks let you touch that call's input and output.

## Reference

### Life events

- **action:service.created**: A service was opened. The return value is ignored.
- **action:service.status_changed**: Its status changed. The return value is ignored.
- **action:service.suspended**: It was suspended. The return value is ignored.
- **action:service.terminated**: It was terminated. The return value is ignored.
- **action:service.cancelled**: It was cancelled. The return value is ignored.
- **action:service.deleted**: Its record was deleted. The return value is ignored.
- **action:service.renewed**: It was renewed. The return value is ignored.
- **action:service.updowngrade.applied**: A plan change was applied. The return value is ignored.

### Gates

Eighteen gates. Two of them split one job in two. A module action called from the panel passes one gate, and the same action from the customer panel passes another. Where your rule holds for both, bind to **both**.

- **gate:service.suspend**: Suspending.
- **gate:service.cancel**: Cancelling.
- **gate:service.delete**: Deleting.
- **gate:service.upgrade**: Upgrading the plan.
- **gate:service.manual_renew**: Renewing by hand.
- **gate:service.status_change**: Changing the status.
- **gate:service.module_action**: A module action from the panel.
- **gate:service.client_tool**: A module action from the customer panel.
- **gate:service.transfer_request**: A transfer request.
- **gate:service.autorenew_toggle**: Switching auto-renewal on and off.

### The provider module

- **action:service.module_ran**: An action ran on the provider module.
- **filter:service.module_result**: What the module returned.
- **filter:service.build_options**: The options going to the module while a service is built. The array changes by reference and the changed array is what gets written; the return value is not used.
- **filter:service.config_fields**: The service's configuration fields.
- **filter:service.module_username**: The username used on the module.
- **action:service.password_changed**: The service password changed.

### The detail screen's data

- **filter:service.detail_data**: The data behind a service detail.
- **filter:service.dashboard.cards**: The cards on a service dashboard.
- **filter:service.dashboard.tools**: The tools on a service dashboard.
- **filter:service.detail_tabs_capabilities**: Which capabilities the detail tabs show.
- **filter:service.upgrade_products**: The products offered for an upgrade.

### A gate and an event together

```php
// A GATE: do not suspend a service under review (ask us first).
Hook::add('gate:service.suspend', 10, function ($service) {
    if (Acme::onHold((int) ($service['id'] ?? 0)))
        return 'This service is under review; the suspend was stopped.';
    return null;
});

// AN EVENT: tell the outside once it was suspended.
Hook::add('action:service.suspended', 10, function ($id, $service) {
    Crm::suspended((int) $id);
});
```

## Pitfalls

> **Automatic actions pass these hooks too**
> 
> Suspending, terminating and renewing also run from **scheduled tasks**. A gate saying "the operator should not do this" also lands on the job running overnight, and the system cannot do its own work. Write a gate thinking about who it stops.

> **The event does not prove the work landed on the server**
> 
> The status hook runs when **our record** changes. Whether the provider module truly closed the account on the server is a separate question, and the record can change even where the module call failed. Where the server side matters, read the filter carrying the module result.

> **The panel and customer paths are separate gates**
> 
> Module actions pass two separate gates: one for the operator in the panel, one for the customer in theirs. Binding to only one means your rule **can be walked around** by the other path. The customer path is also narrower: only the methods a module openly allows can be called.

> **A renewal can show up twice**
> 
> A renewal can come from an invoice being paid or from a manual action, and a subscription collection takes the same path. Writing work that follows a renewal, be ready to run **twice for one period** and weed out the repeat on your side.

## Related Articles

- Order Flow Hooks
- Invoice and Payment Hooks
- Module Lifecycle Hooks
