sausin/laravel-ovh
Sausin/laravel-ovh integrates the OVH API with Laravel, offering a configurable service provider, facade, and straightforward authentication so you can manage OVH services such as domains, hosting, email, SMS, and billing directly from your PHP application.
Install the package and publish its config:
composer require sausin/laravel-ovh
php artisan vendor:publish --provider="Sausin\LaravelOvh\OvhServiceProvider"
Laravel auto-discovers the service provider. The package exposes the OVH API through the Ovh facade:
use Sausin\LaravelOvh\Facades\Ovh;
Configure credentials in .env:
OVH_ENDPOINT=ovh-eu
OVH_APPLICATION_KEY=your-application-key
OVH_APPLICATION_SECRET=your-application-secret
OVH_CONSUMER_KEY=your-consumer-key
Create an OVH application at the API console for your endpoint, then generate a consumer key with access rules covering the exact routes and HTTP methods you need. The first smoke test is:
$me = Ovh::get('/me');
Run it from php artisan tinker. If it returns your OVH account details, credentials and consumer-key rules are working. A common first real use case is DNS automation:
Ovh::post('/domain/zone/example.com/record', [
'fieldType' => 'TXT',
'subDomain' => '_acme-challenge',
'target' => '"verification-token"',
'ttl' => 60,
]);
Ovh::post('/domain/zone/example.com/refresh');
Version note: v7.4.1 is a Laravel 13 compatibility patch for $this binding. It has no new API surface or breaking changes. Use ^7.4.1 if you are on Laravel 13.
Keep OVH calls behind a small application service rather than calling the facade from controllers. This gives you one place for retries, logging, and test doubles.
namespace App\Services;
use Sausin\LaravelOvh\Facades\Ovh;
class OvhDns
{
public function addTxtRecord(string $zone, string $subDomain, string $value): void
{
Ovh::post("/domain/zone/{$zone}/record", [
'fieldType' => 'TXT',
'subDomain' => $subDomain,
'target' => '"' . $value . '"',
'ttl' => 60,
]);
Ovh::post("/domain/zone/{$zone}/refresh");
}
public function records(string $zone): array
{
return Ovh::get("/domain/zone/{$zone}/record");
}
}
Use the facade methods directly for day-to-day API work:
Ovh::get('/domain/zone/example.com/record');
Ovh::post('/domain/zone/example.com/record', $payload);
Ovh::put("/domain/zone/example.com/record/{$id}", $payload);
Ovh::delete("/domain/zone/example.com/record/{$id}");
Wrap write operations in queued jobs when they are part of a larger workflow. OVH API calls can be slow and rate-limited, and jobs give you retry and backoff behavior without blocking requests:
ProcessOvhDnsRecord::dispatch($zone, $record);
Cache read-heavy metadata where freshness is not critical:
$records = Cache::remember(
"ovh:dns:{$zone}:records",
now()->addMinutes(5),
fn () => Ovh::get("/domain/zone/{$zone}/record")
);
For tests, mock the facade when your code uses it directly:
Ovh::shouldReceive('get')
->with('/me')
->once()
->andReturn(['nic' => 'ab12345-ovh']);
For larger applications, define an interface such as OvhClient and bind an adapter implementation in a service provider. That makes it easier to use Laravel’s Http::fake() or a custom fake, because the underlying OVH SDK does not necessarily route through Laravel’s HTTP client.
Common integration points:
GET /domain/zone/* does not automatically allow POST /domain/zone/*/record. Grant the exact method and route patterns you use.ovh-eu application key and consumer key will not work against ovh-ca. Keep endpoint, application key, secret, and consumer key aligned.Ovh::get() is query data; for Ovh::post() and Ovh::put() it is the request body. Do not put body fields into the URL path./. The endpoint host comes from config, so do not pass a full URL.POST requests. A timeout after a successful create can produce duplicate DNS records on retry. Retry idempotent GET calls and treat writes carefully.Http::fake() may not intercept calls made by the underlying OVH SDK/Guzzle stack. Mock the Ovh facade or wrap the client behind your own interface if you need HTTP-level fakes..env, run php artisan config:clear. In deployments, rebuild config cache after injecting secrets.$this binding. If you pinned 7.4.0 and see binding-related errors after a Laravel 13 upgrade, update to ^7.4.1. It is a low-risk patch release.How can I help you explore Laravel packages today?