Hetzner Cloud PHP API Client Documentation

Everything you need to know about using the Tectalic Hetzner Cloud PHP API Client.

Introduction

The Tectalic Hetzner Cloud REST API Client is a package that provides a convenient and straightforward way to interact with the Hetzner Cloud API from your PHP application.

You can purchase this package from https://tectalic.com/apis/hetzner-cloud.

Installation

System Requirements

  • PHP version 7.2.5 or newer (including PHP 8.0 and 8.1)
  • PHP JSON extension installed if using PHP 7.x. As of PHP 8.0, this extension became a core PHP extension so is always enabled.
  • A PSR-18 compatible HTTP client such as ‘Guzzle’ or the ‘Symfony HTTP Client’.

Composer Installation

To install this package into your PHP project, we recommend using Composer.

Please see the detailed instructions on configuring your project to access the Tectalic Composer repository.

You will need to log into the Tectalic account that purchased the Tectalic Hetzner Cloud REST API Client package to access these instructions.

Once you have followed the above instructions, install the package into your project:

composer require tectalic/hetzner-cloud

Manual Installation

If you aren’t using Composer in your PHP project, you can choose to Download the latest release and install it into your PHP project manually.

If doing this, you will need to ensure that all dependencies listed in the package’s composer.json file are also installed.

Usage

After installing the Tectalic Hetzner Cloud REST API Client package into your project, ensure you also have a compatible PSR-18 HTTP client such as ‘Guzzle’ or the Symfony ‘HTTP Client’.

You can use the following code sample and customize it to suit your application.

// Load your project's composer autoloader (if you aren't already doing so).
require_once(__DIR__ . '/vendor/autoload.php');
use Symfony\Component\HttpClient\Psr18Client;
use Tectalic\HetznerCloud\Client;
use Tectalic\HetznerCloud\Manager;
 
// Build a Tectalic Hetzner Cloud REST API Client globally.
$httpClient = new Psr18Client();
Manager::build($httpClient);
 
// or
 
// Build a Tectalic Hetzner Cloud REST API Client manually.
$httpClient = new Psr18Client();
$client = new Client($httpClient, Manager::BASE_URI);

Client Class

The primary class you will interact with is the Client class (Tectalic\HetznerCloud\Client).

This Client class also contains the helper methods that let you quickly access the 82 API Handlers.

Please see below for a complete list of supported handlers and methods.

Supported API Handlers and Methods

This package supports 135 API Methods, which are grouped into 82 API Handlers.

See the table below for a full list of API Handlers and Methods.

API Handler Class and Method Name Description API Verb and URL
Actions::get() Get all Actions GET /actions
Actions::idGet() Get an Action GET /actions/{id}
Certificates::get() Get all Certificates GET /certificates
Certificates::post() Create a Certificate POST /certificates
Certificates::idGet() Get a Certificate GET /certificates/{id}
Certificates::idPut() Update a Certificate PUT /certificates/{id}
Certificates::idDelete() Delete a Certificate DELETE /certificates/{id}
CertificatesActions::idActionsGet() Get all Actions for a Certificate GET /certificates/{id}/actions
CertificatesActions::idActionsActionIdGet() Get an Action for a Certificate GET /certificates/{id}/actions/{action_id}
CertificatesActionsRetry::idActionsRetryPost() Retry Issuance or Renewal POST /certificates/{id}/actions/retry
Datacenters::get() Get all Datacenters GET /datacenters
Datacenters::idGet() Get a Datacenter GET /datacenters/{id}
Firewalls::get() Get all Firewalls GET /firewalls
Firewalls::post() Create a Firewall POST /firewalls
Firewalls::idGet() Get a Firewall GET /firewalls/{id}
Firewalls::idPut() Update a Firewall PUT /firewalls/{id}
Firewalls::idDelete() Delete a Firewall DELETE /firewalls/{id}
FirewallsActions::idActionsGet() Get all Actions for a Firewall GET /firewalls/{id}/actions
FirewallsActions::idActionsActionIdGet() Get an Action for a Firewall GET /firewalls/{id}/actions/{action_id}
FirewallsActionsApplyToResources::idActionsApplyToResourcesPost() Apply to Resources POST /firewalls/{id}/actions/apply_to_resources
FirewallsActionsRemoveFromResources::idActionsRemoveFromResourcesPost() Remove from Resources POST /firewalls/{id}/actions/remove_from_resources
FirewallsActionsSetRules::idActionsSetRulesPost() Set Rules POST /firewalls/{id}/actions/set_rules
FloatingIps::get() Get all Floating IPs GET /floating_ips
FloatingIps::post() Create a Floating IP POST /floating_ips
FloatingIps::idGet() Get a Floating IP GET /floating_ips/{id}
FloatingIps::idPut() Update a Floating IP PUT /floating_ips/{id}
FloatingIps::idDelete() Delete a Floating IP DELETE /floating_ips/{id}
FloatingIpsActions::idActionsGet() Get all Actions for a Floating IP GET /floating_ips/{id}/actions
FloatingIpsActions::idActionsActionIdGet() Get an Action for a Floating IP GET /floating_ips/{id}/actions/{action_id}
FloatingIpsActionsAssign::idActionsAssignPost() Assign a Floating IP to a Server POST /floating_ips/{id}/actions/assign
FloatingIpsActionsChangeDnsPtr::idActionsChangeDnsPtrPost() Change reverse DNS entry for a Floating IP POST /floating_ips/{id}/actions/change_dns_ptr
FloatingIpsActionsChangeProtection::idActionsChangeProtectionPost() Change Floating IP Protection POST /floating_ips/{id}/actions/change_protection
FloatingIpsActionsUnassign::idActionsUnassignPost() Unassign a Floating IP POST /floating_ips/{id}/actions/unassign
Images::get() Get all Images GET /images
Images::idGet() Get an Image GET /images/{id}
Images::idPut() Update an Image PUT /images/{id}
Images::idDelete() Delete an Image DELETE /images/{id}
ImagesActions::idActionsGet() Get all Actions for an Image GET /images/{id}/actions
ImagesActions::idActionsActionIdGet() Get an Action for an Image GET /images/{id}/actions/{action_id}
ImagesActionsChangeProtection::idActionsChangeProtectionPost() Change Image Protection POST /images/{id}/actions/change_protection
Isos::get() Get all ISOs GET /isos
Isos::idGet() Get an ISO GET /isos/{id}
LoadBalancerTypes::get() Get all Load Balancer Types GET /load_balancer_types
LoadBalancerTypes::idGet() Get a Load Balancer Type GET /load_balancer_types/{id}
LoadBalancers::get() Get all Load Balancers GET /load_balancers
LoadBalancers::post() Create a Load Balancer POST /load_balancers
LoadBalancers::idGet() Get a Load Balancer GET /load_balancers/{id}
LoadBalancers::idPut() Update a Load Balancer PUT /load_balancers/{id}
LoadBalancers::idDelete() Delete a Load Balancer DELETE /load_balancers/{id}
LoadBalancersActions::idActionsGet() Get all Actions for a Load Balancer GET /load_balancers/{id}/actions
LoadBalancersActions::idActionsActionIdGet() Get an Action for a Load Balancer GET /load_balancers/{id}/actions/{action_id}
LoadBalancersActionsAddService::idActionsAddServicePost() Add Service POST /load_balancers/{id}/actions/add_service
LoadBalancersActionsAddTarget::idActionsAddTargetPost() Add Target POST /load_balancers/{id}/actions/add_target
LoadBalancersActionsAttachToNetwork::idActionsAttachToNetworkPost() Attach a Load Balancer to a Network POST /load_balancers/{id}/actions/attach_to_network
LoadBalancersActionsChangeAlgorithm::idActionsChangeAlgorithmPost() Change Algorithm POST /load_balancers/{id}/actions/change_algorithm
LoadBalancersActionsChangeDnsPtr::idActionsChangeDnsPtrPost() Change reverse DNS entry for this Load Balancer POST /load_balancers/{id}/actions/change_dns_ptr
LoadBalancersActionsChangeProtection::idActionsChangeProtectionPost() Change Load Balancer Protection POST /load_balancers/{id}/actions/change_protection
LoadBalancersActionsChangeType::idActionsChangeTypePost() Change the Type of a Load Balancer POST /load_balancers/{id}/actions/change_type
LoadBalancersActionsDeleteService::idActionsDeleteServicePost() Delete Service POST /load_balancers/{id}/actions/delete_service
LoadBalancersActionsDetachFromNetwork::idActionsDetachFromNetworkPost() Detach a Load Balancer from a Network POST /load_balancers/{id}/actions/detach_from_network
LoadBalancersActionsDisablePublicInterface::idActionsDisablePublicInterfacePost() Disable the public interface of a Load Balancer POST /load_balancers/{id}/actions/disable_public_interface
LoadBalancersActionsEnablePublicInterface::idActionsEnablePublicInterfacePost() Enable the public interface of a Load Balancer POST /load_balancers/{id}/actions/enable_public_interface
LoadBalancersActionsRemoveTarget::idActionsRemoveTargetPost() Remove Target POST /load_balancers/{id}/actions/remove_target
LoadBalancersActionsUpdateService::idActionsUpdateServicePost() Update Service POST /load_balancers/{id}/actions/update_service
LoadBalancersMetrics::idMetricsGet() Get Metrics for a LoadBalancer GET /load_balancers/{id}/metrics
Locations::get() Get all Locations GET /locations
Locations::idGet() Get a Location GET /locations/{id}
Networks::get() Get all Networks GET /networks
Networks::post() Create a Network POST /networks
Networks::idGet() Get a Network GET /networks/{id}
Networks::idPut() Update a Network PUT /networks/{id}
Networks::idDelete() Delete a Network DELETE /networks/{id}
NetworksActions::idActionsGet() Get all Actions for a Network GET /networks/{id}/actions
NetworksActions::idActionsActionIdGet() Get an Action for a Network GET /networks/{id}/actions/{action_id}
NetworksActionsAddRoute::idActionsAddRoutePost() Add a route to a Network POST /networks/{id}/actions/add_route
NetworksActionsAddSubnet::idActionsAddSubnetPost() Add a subnet to a Network POST /networks/{id}/actions/add_subnet
NetworksActionsChangeIpRange::idActionsChangeIpRangePost() Change IP range of a Network POST /networks/{id}/actions/change_ip_range
NetworksActionsChangeProtection::idActionsChangeProtectionPost() Change Network Protection POST /networks/{id}/actions/change_protection
NetworksActionsDeleteRoute::idActionsDeleteRoutePost() Delete a route from a Network POST /networks/{id}/actions/delete_route
NetworksActionsDeleteSubnet::idActionsDeleteSubnetPost() Delete a subnet from a Network POST /networks/{id}/actions/delete_subnet
PlacementGroups::get() Get all PlacementGroups GET /placement_groups
PlacementGroups::post() Create a PlacementGroup POST /placement_groups
PlacementGroups::idGet() Get a PlacementGroup GET /placement_groups/{id}
PlacementGroups::idPut() Update a PlacementGroup PUT /placement_groups/{id}
PlacementGroups::idDelete() Delete a PlacementGroup DELETE /placement_groups/{id}
Pricing::get() Get all prices GET /pricing
ServerTypes::get() Get all Server Types GET /server_types
ServerTypes::idGet() Get a Server Type GET /server_types/{id}
Servers::get() Get all Servers GET /servers
Servers::post() Create a Server POST /servers
Servers::idGet() Get a Server GET /servers/{id}
Servers::idPut() Update a Server PUT /servers/{id}
Servers::idDelete() Delete a Server DELETE /servers/{id}
ServersActions::idActionsGet() Get all Actions for a Server GET /servers/{id}/actions
ServersActions::idActionsActionIdGet() Get an Action for a Server GET /servers/{id}/actions/{action_id}
ServersActionsAddToPlacementGroup::idActionsAddToPlacementGroupPost() Add a Server to a Placement Group POST /servers/{id}/actions/add_to_placement_group
ServersActionsAttachIso::idActionsAttachIsoPost() Attach an ISO to a Server POST /servers/{id}/actions/attach_iso
ServersActionsAttachToNetwork::idActionsAttachToNetworkPost() Attach a Server to a Network POST /servers/{id}/actions/attach_to_network
ServersActionsChangeAliasIps::idActionsChangeAliasIpsPost() Change alias IPs of a Network POST /servers/{id}/actions/change_alias_ips
ServersActionsChangeDnsPtr::idActionsChangeDnsPtrPost() Change reverse DNS entry for this Server POST /servers/{id}/actions/change_dns_ptr
ServersActionsChangeProtection::idActionsChangeProtectionPost() Change Server Protection POST /servers/{id}/actions/change_protection
ServersActionsChangeType::idActionsChangeTypePost() Change the Type of a Server POST /servers/{id}/actions/change_type
ServersActionsCreateImage::idActionsCreateImagePost() Create Image from a Server POST /servers/{id}/actions/create_image
ServersActionsDetachFromNetwork::idActionsDetachFromNetworkPost() Detach a Server from a Network POST /servers/{id}/actions/detach_from_network
ServersActionsDetachIso::idActionsDetachIsoPost() Detach an ISO from a Server POST /servers/{id}/actions/detach_iso
ServersActionsDisableBackup::idActionsDisableBackupPost() Disable Backups for a Server POST /servers/{id}/actions/disable_backup
ServersActionsDisableRescue::idActionsDisableRescuePost() Disable Rescue Mode for a Server POST /servers/{id}/actions/disable_rescue
ServersActionsEnableBackup::idActionsEnableBackupPost() Enable and Configure Backups for a Server POST /servers/{id}/actions/enable_backup
ServersActionsEnableRescue::idActionsEnableRescuePost() Enable Rescue Mode for a Server POST /servers/{id}/actions/enable_rescue
ServersActionsPoweroff::idActionsPoweroffPost() Power off a Server POST /servers/{id}/actions/poweroff
ServersActionsPoweron::idActionsPoweronPost() Power on a Server POST /servers/{id}/actions/poweron
ServersActionsReboot::idActionsRebootPost() Soft-reboot a Server POST /servers/{id}/actions/reboot
ServersActionsRebuild::idActionsRebuildPost() Rebuild a Server from an Image POST /servers/{id}/actions/rebuild
ServersActionsRemoveFromPlacementGroup::idActionsRemoveFromPlacementGroupPost() Remove from Placement Group POST /servers/{id}/actions/remove_from_placement_group
ServersActionsRequestConsole::idActionsRequestConsolePost() Request Console for a Server POST /servers/{id}/actions/request_console
ServersActionsReset::idActionsResetPost() Reset a Server POST /servers/{id}/actions/reset
ServersActionsResetPassword::idActionsResetPasswordPost() Reset root Password of a Server POST /servers/{id}/actions/reset_password
ServersActionsShutdown::idActionsShutdownPost() Shutdown a Server POST /servers/{id}/actions/shutdown
ServersMetrics::idMetricsGet() Get Metrics for a Server GET /servers/{id}/metrics
SshKeys::get() Get all SSH keys GET /ssh_keys
SshKeys::post() Create an SSH key POST /ssh_keys
SshKeys::idGet() Get a SSH key GET /ssh_keys/{id}
SshKeys::idPut() Update an SSH key PUT /ssh_keys/{id}
SshKeys::idDelete() Delete an SSH key DELETE /ssh_keys/{id}
Volumes::get() Get all Volumes GET /volumes
Volumes::post() Create a Volume POST /volumes
Volumes::idGet() Get a Volume GET /volumes/{id}
Volumes::idPut() Update a Volume PUT /volumes/{id}
Volumes::idDelete() Delete a Volume DELETE /volumes/{id}
VolumesActions::idActionsGet() Get all Actions for a Volume GET /volumes/{id}/actions
VolumesActions::idActionsActionIdGet() Get an Action for a Volume GET /volumes/{id}/actions/{action_id}
VolumesActionsAttach::idActionsAttachPost() Attach Volume to a Server POST /volumes/{id}/actions/attach
VolumesActionsChangeProtection::idActionsChangeProtectionPost() Change Volume Protection POST /volumes/{id}/actions/change_protection
VolumesActionsDetach::idActionsDetachPost() Detach Volume POST /volumes/{id}/actions/detach
VolumesActionsResize::idActionsResizePost() Resize Volume POST /volumes/{id}/actions/resize

Making a Request

There are two ways to make a request to the nominated API Handler and API Method:

If you built the client to be accessible globally, you can use the relevant API Handler Class directly:

use Tectalic\HetznerCloud\Handlers\Actions;
 
(new Actions())->get();

Alternatively, you can access all API Handlers from the client class using the Client class:

$client->actions()->get();

Retrieving the Response

Once you have made a request using one of the two methods outlined above, the next step is to access the response.

You can access the response in different ways. Please choose your preferred one.

Model Responses

Model responses are Data Transfer Object (DTO) style PHP classes, with public properties for each API property.

They offer a structured way of retrieving the response from an API request.

All Response Models are an instance of \Spatie\DataTransferObject\DataTransferObject or \Spatie\DataTransferObject\DataTransferObjectCollection.

After performing the request, use the ->toModel() fluent method to the API Method:

use Tectalic\HetznerCloud\Handlers\Actions;
 
$model = (new Actions())->get()->toModel();

Each API Method’s toModel() call will return the appropriate Model class type for the API Method you have just called.

Associative Array Responses

After performing the request, use the ->toArray() fluent method to the API Method:

use Tectalic\HetznerCloud\Handlers\Actions;
 
$array = (new Actions())->get()->toArray();

In the resulting associative array, the array keys will match the names of the public properties in the relevant Model class.

PSR 7 Response Objects

If you need to access the raw response or inspect the HTTP headers, use the ->getResponse() fluent method to the API Method. It will return a Psr\Http\Message\ResponseInterface:

use Tectalic\HetznerCloud\Handlers\Actions;
 
$response = (new Actions())->get()->getResponse();

Errors

When performing requests with Tectalic Hetzner Cloud REST API Client, specific scenarios will cause a Tectalic\HetznerCloud\Exception\ClientException to be thrown. Please see below for details.

Invalid Usage of the Manager Class

A \LogicException will be thrown if the Manager::build() function is called multiple times, or if Manager::access() is called before calling Manager::build().

Unsuccessful HTTP Response Codes

The Tectalic Hetzner Cloud REST API Client depends on a PSR-18 compatible HTTP client, and that HTTP client should not throw an exception for unsuccessful HTTP response codes.

An unsuccessful response code is classified as one that is not in the range 200-299 (inclusive). Examples of unsuccessful response codes include:

  • Informational responses (100-199)
  • Redirection responses (300-399)
  • Client error responses (400-499)
  • Server error responses (500-599)

If an unsuccessful response code does occur:

  • your HTTP Client will not throw an Exception.
  • the API Handler’s toModel() method will throw a ClientException.
  • the API Handler’s toArray() method will return the response body and not throw a ClientException.
  • The API Handler’s getResponse() method will return the raw response and not throw a ClientException.

Below is an example of how you may wish to use a try/catch block when performing a request so that you can detect and handle unexpected errors.

use Tectalic\HetznerCloud\Client;
use Tectalic\HetznerCloud\ClientException;
use Tectalic\HetznerCloud\Manager;
 
// Build a Tectalic Hetzner Cloud REST API Client globally.
 
Manager::build($httpClient, $auth);
$handler = new Actions();
 
// Perform a request
try {
$model = $handler->get()->toModel();
// Do something with the response model...
} catch (ClientException $e) {
// Error response received. Retrieve the HTTP response code and response body.
$responseBody = $handler->toArray();
$rawResponse = $handler->getResponse()->getResponse();
$responseCode = $handler->getResponse()->getStatusCode();
// Handle the error...
}

HTTP Client Exceptions

If your HTTP client of choice throws an exception other than ClientException, the Tectalic Hetzner Cloud REST API Client Client and its API Handler classes will let these exceptions bubble up.

Consult your HTTP client’s documentation for more details on exception handling.

Tests

The Tectalic Hetzner Cloud REST API Client package includes several types of automated PHPUnit tests to verify the correct operation:

  • Unit Tests
  • Integration Tests

To run these tests, you will need to have installed the Tectalic Hetzner Cloud REST API Client package with its dev dependencies (i.e. not using the --no-dev flag when running composer).

Unit Tests

These PHPUnit tests are designed to:

  • confirm that each API Method assembles a valid request that matches the Hetzner Cloud API OpenAPI specification.
  • verify the behaviour of other parts of the package, such as the Client and Manager classes.

The unit tests can be run using the following command, which needs to be run from this package’s root directory.

composer test:unit

Unit tests do not perform any real requests against the Hetzner Cloud API.

Unit tests are located in the tests/Unit directory.

Integration Tests

Integration tests are located in the tests/Integration directory.

These PHPUnit tests are designed to confirm that each API Method parses a valid response, according to the Hetzner Cloud API OpenAPI specification. Out of the box the integration tests are designed to work with the Prism Mock Server.

Using Prism as the Target

Make sure Prism is installed. Please see the Prism documentation for details on how to install Prism.

Once Prism is installed, you can run prism and the integration tests side by side in separate terminal windows, or using the following command, which need to be run from this package’s root directory.

echo "> Starting Prism server"
prism mock tests/openapi.json >/dev/null 2>&1 &
PRISM_PID=$!
sleep 2
echo " => Started"
composer test:integration
kill $PRISM_PID

Those commands will start the Prism mock server, then run the integration tests, and then stop the Prism mock server when the tests are completed.

In this case the integration tests do not perform any real requests against the Hetzner Cloud API.

Using a Different Target

By setting the HETZNER_CLOUD_CLIENT_TEST_BASE_URI environment variable, you can set a different API endpoint target for the integration tests.

For example, instead of using Prism, you can use a different mocking/staging/test server of your choice, or you can use the Hetzner Cloud API’s live endpoints.

After your setup is complete simply run the following command.

composer test:integration

We do not recommend running integration tests against the live Hetzner Cloud API endpoints. This is because the tests will send example data to all endpoints, which can result in new data being created, or existing data being deleted.

Support

If you have any questions or feedback, you can submit a support request to the Tectalic developers by going to https://tectalic.com/support/hetzner-cloud.

License

This software is copyright (c) Tectalic.

For the full copyright and license information, please view the ‘LICENSE’ file distributed with the source code.

Last updated 27 Oct 2022

Tectalic Hetzner Cloud PHP API Client