PHPackages                             chuckbartowski/ovh-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. chuckbartowski/ovh-sdk

ActiveLibrary[API Development](/categories/api)

chuckbartowski/ovh-sdk
======================

PHP SDK for the OVHcloud API — native request signing, typed clients and high-level modules for every product

v1.0.0(yesterday)00MITPHP &gt;=8.2

Since Jul 22Compare

[ Source](https://github.com/ChuckBartowski11/OVH)[ Packagist](https://packagist.org/packages/chuckbartowski/ovh-sdk)[ RSS](/packages/chuckbartowski-ovh-sdk/feed)WikiDiscussions Synced today

READMEChangelogDependencies (6)Versions (2)Used By (0)

[![OVHcloud SDK PHP](.github/banner.svg)](.github/banner.svg)☁️ OVHcloud SDK for PHP
=======================

[](#️-ovhcloud-sdk-for-php)

**A modern, fully typed PHP SDK for the entire OVHcloud API — every product, native request signing, no wrapper dependency.**

[![PHP Version](https://camo.githubusercontent.com/37e9353129a38e0a10457e9be783cef965146675bbe12d6ae081c64cfe96d447/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d253345253344253230382e322d3737374242343f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://www.php.net/)[![Symfony](https://camo.githubusercontent.com/535d441eb72e052f085beb20c298850a907064fde523cdd591b21cbdf015cbac/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53796d666f6e792d362e34253230253743253230372e782d3030303030303f6c6f676f3d73796d666f6e79266c6f676f436f6c6f723d7768697465)](https://symfony.com/)[![Tests](https://camo.githubusercontent.com/e0250db3fd88212ebf8fa724d810376eab55849283b2e08b27311d4b8e3c3e44/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d313525323070617373696e672d627269676874677265656e3f6c6f676f3d676974687562)](tests/)[![Coverage](https://camo.githubusercontent.com/21e7e484945aa49a099966af1c38a8b2d45e194899803a2d436cd08d688aa9cd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f70726f64756374732d31392532306d6f64756c65732d626c7565)](#api-reference)[![License](https://camo.githubusercontent.com/3921b6a636b7d3fc4db90f929b9047fb47fa4fdd6233a2b5fa60b827480fc2c5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d79656c6c6f77)](LICENSE)

*Domains &amp; DNS · Public Cloud · Dedicated · VPS · Kubernetes · Web Hosting · Email · IP · vRack · Load Balancer · SMS*

[Installation](#installation) · [Authentication](#authentication) · [API Reference](#api-reference) · [Error Handling](#error-handling)

---

```
$ovh = new Ovh(new OvhClient($appKey, $appSecret, $consumerKey));

$ovh->domains()->addRecord('example.com', 'A', '203.0.113.10', 'www');
$ovh->cloud()->createInstance($projectId, ['name' => 'web01', 'flavorId' => '...', 'imageId' => '...']);
$ovh->dedicatedServers()->reboot('ns3000000.ip-1-2-3.eu');
```

Framework-agnostic core — usable from any PHP project, script, or worker — with an optional bundle for first-class Symfony integration. **The OVHcloud `$1$` request signature is implemented natively** (no dependency on the official `ovh/ovh` wrapper), with automatic clock-drift correction, typed exceptions, opt-in retries, and a comment-free, strictly typed codebase (PHP 8.2+, `declare(strict_types=1)` everywhere).

---

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Authentication](#authentication)
- [Quick Start (plain PHP)](#quick-start-plain-php)
- [Symfony Integration (optional)](#symfony-integration-optional)
- [Architecture](#architecture)
- [API Reference](#api-reference)
    - [Account (`me`)](#account-me)
    - [Domains &amp; DNS](#domains--dns)
    - [Dedicated servers](#dedicated-servers)
    - [VPS](#vps)
    - [Public Cloud](#public-cloud)
    - [Managed Databases &amp; Kubernetes](#managed-databases--kubernetes)
    - [Web Hosting](#web-hosting)
    - [Email](#email)
    - [IP](#ip)
    - [vRack](#vrack)
    - [Load Balancer](#load-balancer)
    - [CDN, Licenses, Orders, SMS, Logs, Support, VoIP](#cdn-licenses-orders-sms-logs-support-voip)
    - [Generic access](#generic-access)
- [Responses](#responses)
- [Error Handling](#error-handling)
- [Testing](#testing)
- [Security Notes](#security-notes)
- [WHMCS module](#whmcs-module)
- [License](#license)

---

Features
--------

[](#features)

🔐 **Native request signing**The OVHcloud `$1$` SHA-1 signature scheme implemented from scratch — no `ovh/ovh` dependency — with lazy clock-drift correction against `/auth/time`🧩 **19 product modules**One facade covering the whole `api.ovh.com/1.0` surface: domains, cloud, dedicated, VPS, Kubernetes, databases, hosting, email, IP, vRack, load balancers, CDN, licenses, orders, SMS, logs, support, VoIP🌍 **All endpoints**`ovh-eu`, `ovh-ca`, `ovh-us`, `kimsufi-eu/ca`, `soyoustart-eu/ca` — pick yours or pass a custom base URL🎫 **Credential flow built in**`requestCredentials()` mints a consumer key with the access rules you need and returns the validation URL🚨 **Production-grade errors**400/403/404/409/429 mapped to dedicated exceptions exposing OVHcloud's `errorCode`; opt-in automatic retries with backoff🔓 **Nothing sealed off**The client's `get`/`post`/`put`/`delete` accept any path, and `me()->fetch()` / `cloud()->fetch()` reach any sub-resource, so 100% of the API is one call away🛠 **Framework-agnostic**Only hard dependency is `symfony/http-client`; the optional Symfony bundle adds semantic config and autowiring✅ **Fully unit-tested**15 tests against `MockHttpClient`, including exact signature verification — no network requiredRequirements
------------

[](#requirements)

DependencyVersionPHP&gt;= 8.2OVHcloudan application key + secret, and a consumer key ([create here](https://api.ovh.com/createToken/))Symfony6.4 LTS or 7.x — **optional**, only for the bundle integrationInstallation
------------

[](#installation)

If the package is published on [Packagist](https://packagist.org/packages/chuckbartowski/ovh-sdk):

```
composer require chuckbartowski/ovh-sdk
```

Authentication
--------------

[](#authentication)

OVHcloud signs every request with `X-Ovh-Signature: $1$` + `sha1(secret + "+" + consumerKey + "+" + method + "+" + url + "+" + body + "+" + timestamp)`. This SDK does all of it for you — you only provide three credentials:

- **Application key** + **Application secret** — identify your app ([create an application](https://api.ovh.com/createApp/)).
- **Consumer key** — identifies the authorization granted to your app on an account.

The fastest path is [api.ovh.com/createToken](https://api.ovh.com/createToken/) which gives you all three at once. To mint a consumer key programmatically with a chosen scope:

```
$client = new OvhClient($appKey, $appSecret, null, 'ovh-eu');

$creds = $client->requestCredentials(
    accessRules: [
        ['method' => 'GET',    'path' => '/*'],
        ['method' => 'POST',   'path' => '/domain/*'],
        ['method' => 'DELETE', 'path' => '/domain/zone/*'],
    ],
    redirection: 'https://your-app.example.com/ovh/callback',
);

$consumerKey  = $creds->data('consumerKey');   // store this
$validationUrl = $creds->data('validationUrl'); // user opens this once to approve
```

The clock-drift correction is automatic: the first signed call fetches OVHcloud's server time from `/auth/time` and offsets every subsequent timestamp, so a skewed local clock never breaks the signature.

Quick Start (plain PHP)
-----------------------

[](#quick-start-plain-php)

```
use ChuckBartowski\OvhSdk\Client\OvhClient;
use ChuckBartowski\OvhSdk\Ovh;

$ovh = new Ovh(new OvhClient(
    applicationKey: getenv('OVH_APP_KEY'),
    applicationSecret: getenv('OVH_APP_SECRET'),
    consumerKey: getenv('OVH_CONSUMER_KEY'),
    endpoint: 'ovh-eu',
));

$account = $ovh->me()->info();
$ovh->domains()->addRecord('example.com', 'A', '203.0.113.10', 'www');
$ovh->domains()->refreshZone('example.com');
```

Client constructor signature:

```
new OvhClient(
    string $applicationKey,
    string $applicationSecret,
    ?string $consumerKey = null,              // null → only requestCredentials() is allowed
    string $endpoint = 'ovh-eu',              // or a full custom base URL
    float $timeout = 30.0,
    bool $retryFailed = false,                // retry 429/5xx with exponential backoff
    int $maxRetries = 3,
    ?HttpClientInterface $httpClient = null,  // inject your own (proxy, scoped, mock…)
);
```

Symfony Integration (optional)
------------------------------

[](#symfony-integration-optional)

Register the bundle, then create `config/packages/ovh_sdk.yaml`:

```
ovh_sdk:
    application_key: '%env(OVH_APP_KEY)%'
    application_secret: '%env(OVH_APP_SECRET)%'
    consumer_key: '%env(OVH_CONSUMER_KEY)%'
    endpoint: 'ovh-eu'
    retry_failed: true
```

The `Ovh` facade is then autowirable in controllers, services, commands, and message handlers.

Architecture
------------

[](#architecture)

```
src/
├── OvhSdkBundle.php             Symfony bundle: config tree + service wiring (optional)
├── Ovh.php                      Facade: entry point for all modules
├── Client/
│   └── OvhClient.php            Native $1$ signing, clock-drift, endpoints, retries, credential flow
├── Response/
│   └── ApiResponse.php          Normalized response (+ items/first/as/asList helpers)
├── Exception/
│   ├── OvhSdkExceptionInterface.php   ApiException.php
│   ├── ResourceNotFoundException.php  ForbiddenException.php
│   ├── ConflictException.php          InvalidRequestException.php
│   ├── RateLimitException.php         AuthenticationException.php   TransportException.php
└── Api/
    ├── AbstractApi.php          MeApi.php            DomainApi.php        DedicatedServerApi.php
    ├── VpsApi.php               CloudApi.php         CloudDatabaseApi.php KubernetesApi.php
    ├── WebHostingApi.php        EmailApi.php         IpApi.php            VrackApi.php
    ├── LoadBalancerApi.php      CdnApi.php           LicenseApi.php       OrderApi.php
    └── SmsApi.php               DbaasLogsApi.php     SupportApi.php       VoipApi.php

```

API Reference
-------------

[](#api-reference)

Every method returns an [`ApiResponse`](#responses) and throws on failure. Service names (domains, VPS, dedicated servers…) are URL-encoded for you.

### Account (`me`)

[](#account-me)

`$ovh->me()` — `info()`, `update()`, `bills()` / `bill(id)`, `orders()` / `order(id)`, `paymentMethods()`, `contacts()`, SSH keys (`sshKeys`, `addSshKey`, `deleteSshKey`), API credentials (`apiApplications`, `apiCredentials`, `revokeCredential`), `iamPolicies()`, and `fetch(path)` for any other `/me/*` endpoint.

### Domains &amp; DNS

[](#domains--dns)

`$ovh->domains()` — domain lifecycle (`list`, `find`, `serviceInfos`, `nameservers`, `updateNameservers`, `dnssec`) and the full DNS zone editor:

MethodEndpoint`zones()` / `zone(name)``/domain/zone``records(zone, filters)` / `record(zone, id)``/domain/zone/{zone}/record``addRecord(zone, fieldType, target, subDomain, ttl)``POST …/record``updateRecord(zone, id, fields)` / `deleteRecord(zone, id)``PUT`/`DELETE …/record/{id}``refreshZone(zone)``POST …/refresh` — **required to apply record changes**`exportZone(zone)`BIND export```
$id = $ovh->domains()->addRecord('example.com', 'MX', '10 mail.example.com.', '')->data('id');
$ovh->domains()->refreshZone('example.com');
```

### Dedicated servers

[](#dedicated-servers)

`$ovh->dedicatedServers()` — `list`, `find`, `update`, `serviceInfos`, `hardware`, `network`, `reboot`, `reinstall(name, options)` + `installStatus`, `bootOptions`, `setMonitoring`, `ipmiAccess`, `interventions`, `tasks`.

### VPS

[](#vps)

`$ovh->vps()` — `list`, `find`, `update`, power (`reboot`, `start`, `stop`), `reinstall(name, options)`, `images`, `ips`, snapshots (`snapshots`, `createSnapshot`), `disks`, `tasks`.

### Public Cloud

[](#public-cloud)

`$ovh->cloud()` — every method takes the `$projectId` first:

GroupMethodsProjects`projects()`, `project(id)`, `usageCurrent(id)`Instances`instances`, `instance`, `createInstance`, `deleteInstance`, `rebootInstance`, `startInstance`, `stopInstance`, `reinstallInstance`, `resizeInstance`Volumes`volumes`, `createVolume`, `deleteVolume`, `attachVolume`, `detachVolume`, `volumeSnapshots`Catalog`images`, `flavors`, `regions`Network`privateNetworks`, `createPrivateNetwork`, `publicNetworks`Access`sshKeys`, `addSshKey`, `users`, `createUser`, `storageContainers`Anything else on a project: `cloud()->fetch($projectId, '/…')`.

### Managed Databases &amp; Kubernetes

[](#managed-databases--kubernetes)

`$ovh->cloudDatabases()` — `services(projectId)`, `list(projectId, engine)` (`postgresql`, `mysql`, `redis`, `mongodb`, `kafka`…), `create`, `deleteCluster`, `databases`, `users`, `createUser`, `backups`. `$ovh->kubernetes()` — `clusters`, `cluster`, `create`, `update`, `deleteCluster`, `kubeconfig`, `reset`, node pools (`nodePools`, `createNodePool`, `updateNodePool`, `deleteNodePool`), `nodes`.

### Web Hosting

[](#web-hosting)

`$ovh->webHosting()` — `list`, `find`, attached domains, databases (`databases`, `createDatabase`), `cron`, `users`, SSL (`ssl`, `requestSsl`), `ovhConfigs`, `tasks`.

### Email

[](#email)

`$ovh->email()` — MX Plan (`domains`, `accounts`, `createAccount`, `deleteAccount`, `changePassword`, redirections, mailing lists) and Exchange (`exchangeServices`, `exchangeAccounts`).

### IP

[](#ip)

`$ovh->ips()` — `list`, `find`, reverse DNS (`reverse`, `setReverse`, `deleteReverse`), `move`, `park`, firewall (`firewall`, `enableFirewall`, `firewallRules`, `addFirewallRule`), DDoS mitigation (`mitigation`, `enableMitigation`).

### vRack

[](#vrack)

`$ovh->vrack()` — `list`, `find`, and membership management: dedicated servers, cloud projects, IP blocks (`add`/`remove` for each).

### Load Balancer

[](#load-balancer)

`$ovh->loadBalancers()` — IPLB services: `frontends`/`createFrontend`, `backends`/`createBackend`, `servers`/`addServer`, `pendingChanges`, and `refresh()` to apply staged changes.

### CDN, Licenses, Orders, SMS, Logs, Support, VoIP

[](#cdn-licenses-orders-sms-logs-support-voip)

- `$ovh->cdn()` — dedicated &amp; website CDN, domains, `flushCache`.
- `$ovh->licenses()` — Windows, cPanel, Plesk, DirectAdmin, Office licenses.
- `$ovh->orders()` — cart lifecycle (`createCart`, `addItem`, `checkout`) and public `catalog`.
- `$ovh->sms()` — `send(service, receivers, message)`, jobs, outgoing/incoming, senders.
- `$ovh->dbaasLogs()` — Logs Data Platform: streams, dashboards, inputs, aliases.
- `$ovh->support()` — tickets (`create`, `reply`, `close`, `messages`).
- `$ovh->voip()` — Telephony: billing accounts, lines, numbers, consumption, `click2Call`.

### Generic access

[](#generic-access)

Any endpoint not wrapped by a module stays one call away — signing, endpoint and error handling still apply:

```
$ovh->client()->get('/dedicated/nasha');
$ovh->client()->post('/cloud/project/'.$id.'/ai/notebook', $payload);
```

Responses
---------

[](#responses)

```
$response = $ovh->domains()->records('example.com');

$response->success;       // bool
$response->statusCode;    // int
$response->data;          // decoded JSON (OVHcloud often returns arrays of IDs)
$response->items();       // list form, e.g. [12, 34, 56]
$response->first();       // first item or null
$response->errorCode;     // OVHcloud error code on failure, e.g. 'NOT_FOUND'
$response->as(Model::class);      // hydrate a single object (bring your own model)
$response->asList(Model::class);  // hydrate a collection
```

Note the OVHcloud idiom: list endpoints usually return **arrays of identifiers** (record IDs, service names), which you then fetch individually — `records()` returns IDs, `record($zone, $id)` returns the detail.

Error Handling
--------------

[](#error-handling)

All SDK exceptions implement `OvhSdkExceptionInterface`:

ExceptionThrown whenExtras`ApiException`The API reported a failure (modules validate automatically)`getErrors()`, `getStatusCode()`, `getErrorCode()`, `getRaw()`↳ `InvalidRequestException`HTTP 400 (bad parameters, invalid signature…)↳ `ForbiddenException`HTTP 403 (consumer key lacks the access rule)↳ `ResourceNotFoundException`HTTP 404↳ `ConflictException`HTTP 409↳ `RateLimitException`HTTP 429`AuthenticationException`Missing credentials, or HTTP 401 (invalid/expired consumer key)thrown *before* any request when credentials are missing`TransportException`Network error, TLS failure, timeout, or invalid JSONwraps the `symfony/http-client` exception```
try {
    $ovh->domains()->deleteRecord('example.com', $id);
} catch (ForbiddenException) {
    // consumer key was not granted DELETE on /domain/zone/*
}
```

Testing
-------

[](#testing)

The suite runs entirely offline against `MockHttpClient` — including a test that recomputes the `$1$` signature byte-for-byte:

```
composer install
vendor/bin/phpunit
```

Security Notes
--------------

[](#security-notes)

- The application secret and consumer key are passed with `#[\SensitiveParameter]`, so they never appear in stack traces.
- Scope consumer keys tightly with `accessRules` — grant `GET /domain/*`, not `ALL /*`, when a service only reads domains.
- Keep credentials in `.env.local` or your secret vault — never commit them.
- Destructive calls (`deleteInstance`, `deleteRecord`, `deleteCluster`, dedicated `reinstall`) are irreversible — gate them behind confirmation flows.

WHMCS module
------------

[](#whmcs-module)

A ready-to-use **WHMCS registrar module** ships in [`whmcs/modules/registrars/ovhsdk/`](whmcs/modules/registrars/ovhsdk). It plugs OVHcloud domains into WHMCS's DNS and nameserver management through this SDK.

**Install**

1. `composer require chuckbartowski/ovh-sdk` in your WHMCS root.
2. Copy the `ovhsdk` folder into `/modules/registrars/`.
3. Activate *OVHcloud (SDK)* in *System Settings » Domain Registrars* and enter your **application key / secret / consumer key** and endpoint.

WHMCS actionSDK callGet / Save nameservers`domains()->records(... NS)` / `updateNameservers()`Get DNS records`domains()->records()` + `record()` (MX priority split out)Save DNS recordsreplace all records, then `refreshZone()`Domain **registration and transfers** go through OVHcloud's order cart (`orders()`), which is a multi-step purchase flow — the registrar hooks above cover the day-to-day DNS management that WHMCS drives automatically.

License
-------

[](#license)

MIT

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

1d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5c2b5f7349c25e2adb9edc6908f591c166fb645d4cbded24ff0e79423568214c?d=identicon)[ChuckBartowski11](/maintainers/ChuckBartowski11)

---

Tags

phpapisdkclouddomainovhovhcloudhosting

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/chuckbartowski-ovh-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/chuckbartowski-ovh-sdk/health.svg)](https://phpackages.com/packages/chuckbartowski-ovh-sdk)
```

###  Alternatives

[bitrix24/b24phpsdk

An official PHP library for the Bitrix24 REST API

10244.2k5](/packages/bitrix24-b24phpsdk)[deepseek-php/deepseek-php-client

deepseek PHP client is a robust and community-driven PHP client library for seamless integration with the Deepseek API, offering efficient access to advanced AI and data processing capabilities.

46688.8k5](/packages/deepseek-php-deepseek-php-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
