# Service Lifecycle

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

The five endpoints that suspend, unsuspend, cancel, reinstall and repassword a service.

## Overview

These five endpoints change the **state** of a service. They are unlike editing data fields. Each one makes the provider do work, so the record and the account move together.

Leave `apply_on_module` out and the sensible thing is assumed. On a service with a module the operation reaches the provider; on one without, only the record changes. Reinstalling and changing the password **do not run without a module**, because all the work they do is at the provider.

## Reference

### Suspending a Service

post/api/v1/admin/services/{id}/suspend

`Services/SuspendService` admin reaches the module

Suspends the service and stops the account at the provider too.

Body 3

reasonstringWhy it was suspended. It goes on the record and reaches the client if a notification is sent.

notifyboolSends the client a notification.

apply_on_moduleboolApplies the operation at the provider too. Left out, it is on for a service with a module and off for one without.

Response fields data — 3

statusstringThe status afterwards.

idintService id.

applied_on_moduleboolWhether it reached the provider. False means the WISECP record changed while the account on the server did not.

Errors 2

not_found404No such service.

insufficient_scope403The key lacks the required scope.

Request cURL JavaScript PHP (HTTP) PHP (Internal)

```bash
curl -X POST 'https://panel.example.com/api/v1/admin/services/506/suspend' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"reason":"Awaiting payment","notify":true}'
```

```javascript
const res = await fetch('https://panel.example.com/api/v1/admin/services/506/suspend', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ reason: 'Awaiting payment', notify: true }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/suspend');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'reason' => 'Awaiting payment',
        'notify' => true,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Services()->SuspendService([
    'id'     => 506,
    'reason' => 'Awaiting payment',
    'notify' => true,
]);

// If the status changed but it never reached the module, the account KEEPS running.
if (!($response['data']['applied_on_module'] ?? false)) {
    // needs a hand
}
```

Response 200

```json
{
  "data": {
    "status": "suspended",
    "id": 506,
    "applied_on_module": true
  }
}
```

### Unsuspending a Service

post/api/v1/admin/services/{id}/unsuspend

`Services/UnsuspendService` admin reaches the module

Puts a suspended service back to work and reopens the account at the provider.

Body 2

notifyboolSends the client a notification.

apply_on_moduleboolApplies the operation at the provider too. Left out, it is on for a service with a module and off for one without.

Response fields data — 3

statusstringThe status afterwards.

idintService id.

applied_on_moduleboolWhether it reached the provider. False means the WISECP record changed while the account on the server did not.

Errors 2

not_found404No such service.

insufficient_scope403The key lacks the required scope.

Request cURL JavaScript PHP (HTTP) PHP (Internal)

```bash
curl -X POST 'https://panel.example.com/api/v1/admin/services/506/unsuspend' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"notify":true}'
```

```javascript
const res = await fetch('https://panel.example.com/api/v1/admin/services/506/unsuspend', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ notify: true }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/unsuspend');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['notify' => true]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Services()->UnsuspendService(['id' => 506, 'notify' => true]);
```

### Cancelling a Service

post/api/v1/admin/services/{id}/cancel

`Services/CancelService` admin cannot be undone

Cancels the service and closes the account at the provider.

Body 3

reasonstringWhy it was cancelled.

notifyboolSends the client a notification.

apply_on_moduleboolApplies the operation at the provider too. Left out, it is on for a service with a module and off for one without.

Response fields data — 3

statusstringThe status afterwards.

idintService id.

applied_on_moduleboolWhether it reached the provider. False means the WISECP record changed while the account on the server did not.

Errors 2

not_found404No such service.

insufficient_scope403The key lacks the required scope.

Request cURL JavaScript PHP (HTTP) PHP (Internal)

```bash
curl -X POST 'https://panel.example.com/api/v1/admin/services/506/cancel' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"reason":"Customer request","notify":true}'
```

```javascript
const res = await fetch('https://panel.example.com/api/v1/admin/services/506/cancel', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ reason: 'Customer request', notify: true }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/cancel');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'reason' => 'Customer request',
        'notify' => true,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// The panel asks for the admin password here; on the API the key's scope is enough.
$response = Api::Services()->CancelService([
    'id'     => 506,
    'reason' => 'Customer request',
]);
```

### Reinstalling a Service

post/api/v1/admin/services/{id}/reinstall

`Services/ReinstallService` admin the data goes

Deletes the account at the provider and builds it again. It does not run without a module.

Body —

——No body is needed, so send an empty one. The module rebuilds the account from the stored service record; nothing can be overridden from the call.

Response fields data — 2

statusstringThe outcome.

idintService id.

Errors 4

not_found404No such service.

no_module422The service has no module attached.

module_failed500The module could not complete the operation.

insufficient_scope403The key lacks the required scope.

Request cURL JavaScript PHP (HTTP) PHP (Internal)

```bash
curl -X POST 'https://panel.example.com/api/v1/admin/services/506/reinstall' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch('https://panel.example.com/api/v1/admin/services/506/reinstall', {
  method: 'POST',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/reinstall');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Read the capability first: without a module this endpoint answers 'no_module'.
$service = Api::Services()->GetService(['id' => 506])['data'];

if ($service['capabilities']['can_reinstall'] ?? false) {
    Api::Services()->ReinstallService(['id' => 506]);
}
```

Response 200 422

```json
{
  "data": {
    "status": "reinstalled",
    "id": 506
  }
}
```

```json
{
  "error": {
    "code": "no_module",
    "message": "Service has no module to reinstall."
  }
}
```

### Changing the Service Password

put/api/v1/admin/services/{id}/password

`Services/SetServicePassword` admin needs a module

Changes the password at the provider and stores the new one encrypted on the service.

Body 2

passwordstringrequiredThe new password.

notifyboolSends the new sign-in details to the client. The service activation template is used.

Response fields data — 2

statusstringThe outcome.

idintService id.

Errors 5

not_found404No such service.

no_module422The service has no module attached.

password_required422The password was empty.

module_failed500The module could not complete the operation.

insufficient_scope403The key lacks the required scope.

Request cURL JavaScript PHP (HTTP) PHP (Internal)

```bash
curl -X PUT 'https://panel.example.com/api/v1/admin/services/506/password' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"password":"S3cretP@ss!","notify":true}'
```

```javascript
const res = await fetch('https://panel.example.com/api/v1/admin/services/506/password', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ password: newPassword, notify: true }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/password');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'password' => $newPassword,
        'notify'   => true,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// The password changes at the PROVIDER first, then on the record; if the module fails, neither moves.
$response = Api::Services()->SetServicePassword([
    'id'       => 506,
    'password' => $newPassword,
    'notify'   => true,
]);
```

## Pitfalls

> **The status can change without reaching the server**
> 
> Suspend, unsuspend and cancel can return `200` without ever reaching the provider; `applied_on_module` on the response tells you. When it is false the WISECP record changed while the account **keeps running** on the server. A client reading only the status code will not see it.

> **Reinstalling wipes the account**
> 
> This endpoint does not repair an account: it **deletes** the one at the provider and builds a fresh one. Everything inside goes. Running it as a troubleshooting step is the quickest way to lose the data a client keeps there. Make sure there is a backup first.

> **The password changes at the provider first**
> 
> The new password is written to the provider first and only then stored encrypted on the service. If the module fails neither changes and you get `module_failed`. The stored password and the one on the server are not expected to drift apart. Even so, keep your own copy of the new password: it cannot be read back from the record.

> **The panel asks for a password, the API for a scope**
> 
> Cancelling asks for the admin password in the panel. The API has no such second step: the key's scope is enough. Hand out a key carrying this scope knowing exactly who holds it.

## Related Articles

- [Service Endpoints](https://dev.wisecp.com/en/service-endpoints)
- [Renewal and Cancellation](https://dev.wisecp.com/en/renewal-cancellation)
- [Service Settings and Server](https://dev.wisecp.com/en/service-settings-and-server)
