---
title: "The Certificates facade — Certificates for Laravel | Roundly"
description: "The whole Certificates facade in one place — issuance, renew, revoke and expire, registry-wide renewDue, sync and prune, the for() handle and drivers."
url: https://roundly-consulting.com/open-source/docs/certificates-for-laravel/facade
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Certificates for Laravel](https://roundly-consulting.com/open-source/docs/certificates-for-laravel.md)

# The Certificates facade

RoundlyConsulting\\Certificates\\Facades\\Certificates is the recommended entry point. Its root is CertificatesManager, a container singleton, and every state-changing method runs through an action — so the facade, an injected manager and Certificates::fake() all see the same calls. A tour of the surface:

```php
use RoundlyConsulting\Certificates\DataTransferObjects\IssueCertificateData;
use RoundlyConsulting\Certificates\Facades\Certificates;

// Issue
Certificates::issueIfMissing('app.example.com');
Certificates::issue(IssueCertificateData::make('app.example.com'));

// Lifecycle — a registry Certificate or a domain (its most recent row)
Certificates::renew('app.example.com');
Certificates::renewLater('app.example.com');
Certificates::revoke($certificate, 'key compromise');
Certificates::expire('app.example.com');

// The whole registry
Certificates::expiring(14);            // Collection<int, Certificate>, soonest first
Certificates::renewDue();              // RenewalReport
Certificates::sync('kubernetes');      // int rows written
Certificates::prune(30);               // int rows soft-deleted

// One domain — fluent issuance, reads and the same lifecycle verbs
Certificates::for('app.example.com')->using('acme')->issue();
Certificates::for('app.example.com')->renew();

// Reads, drivers and scoping
Certificates::find('app.example.com');
Certificates::statusReport('app.example.com', fresh: true);
Certificates::driver('acme');
Certificates::extend('vault', fn () => new VaultCertificateProvider());
Certificates::on('tenant')->renewDue();
```

## Issuance and lifecycle

Every lifecycle verb takes a registry Certificate or a domain, which resolves to its most recent row on the bound connection — matched as the primary domain exactly, so a host that is only a SAN of another certificate is not found. An unknown domain, or a status that cannot make the move (renewing a revoked certificate, say), throws CertificateException — renewLater() included: it checks the status before it queues anything:

| Method | Returns | Purpose |
| --- | --- | --- |
| `issue(IssueCertificateData $data)` | Certificate | Provision and record from a DTO; throws ProvisioningInProgressException while another process provisions the same certificate, and CertificateException when another domain already holds its name. |
| `issueIfMissing(string $domain)` | Certificate | The active certificate already covering the domain — its own row, else a SAN certificate listing it — or a new issuance. |
| `generate(string $domain)` | bool | Provision — full lifecycle with a registry, straight through the provider without one; false while the certificate’s lock is held. |
| `renew(Certificate\|string $certificate)` | Certificate | Issued/Renewed/Failed (or a stuck Renewing row) → Renewed, now, through the certificate’s own driver, under its provisioning lock — a concurrent renewal throws ProvisioningInProgressException. |
| `renewLater(Certificate\|string $certificate)` | Certificate | Check the status now, then queue RenewCertificateJob on renewal.queue. |
| `renewDue(?int $thresholdDays = null, bool $queue = false)` | RenewalReport | Renew or queue everything expiring within the threshold or already past expiry (failed and stuck renewing rows included); one failure never stops the rest. |
| `revoke(Certificate\|string $certificate, ?string $reason = null)` | Certificate | Issued/Renewed → Revoked, fires CertificateRevoked. Registry only — the CA is not contacted. |
| `expire(Certificate\|string $certificate)` | Certificate | Issued/Renewed → Expired, fires CertificateExpired. |
| `sync(?string $driver = null)` | int | Pull a driver’s live certificates into the registry, settling in-flight rows with their events; never un-revokes a row. Returns rows written. |
| `prune(int $days = 30, CertificateStatus\|string\|null $status = null)` | int | Soft-delete stale expired, failed and revoked rows — or exactly $status. |

## The domain handle, reads and drivers

| Method | Returns | Purpose |
| --- | --- | --- |
| `for(string\|array $domain)` | CertificateBuilder | The domain handle — fluent issuance, reads and the lifecycle verbs. |
| `find(string $domain, ?string $driver = null)` | ?Certificate | Latest registry record with the domain as its primary domain. |
| `status(string $domain, ?string $driver = null)` | ?CertificateStatus | Registry status of the certificate covering the domain — its own row first, else the newest SAN certificate listing it. |
| `statusReport(string $domain, ?string $driver = null, bool $fresh = false)` | ?CertificateStatusReport | Live, cache-aware status from the provider. |
| `expiring(?int $days = null, ?string $driver = null)` | Collection<Certificate> | Issued, Renewed and Failed rows (and stuck Renewing ones) expiring within $days or already past expiry (default renewal.threshold\_days), soonest first. |
| `get()` | Collection<RemoteCertificate> | Certificates the default driver manages. |
| `exists(string $domain, ?string $driver = null)` | bool | Provider check on $driver (the default driver when null). |
| `monitorExpiry(Certificate $certificate, ?Model $notifiable = null)` | PendingScheduledCheck | Schedule an alerts expiry monitor on the certificate’s own connection. |
| `driver(?string $name = null)` | CertificateProvider | Resolve a provider (default when null). |
| `extend(string $driver, Closure $callback)` | CertificatesManager | Register a custom driver on CertificateProviderManager. |
| `on(?string $connection)` | CertificatesManager | Connection-bound clone for multi-tenant registries. |
| `certificateName(string $domain)` | string | Deterministic, lowercase DNS-1123 certificate name (\*. becomes wildcard-, at most 253 characters). |
| `fake()` | CertificatesFake | Swap in the in-memory recording fake (see Testing). |

Certificates::for($domain) is a handle for one domain (or a SAN set led by its first domain): fluent issuance, reads, and renew(), renewLater(), revoke() and expire() on that domain’s row — see Fluent builder. With using($driver) it only ever touches that driver’s row.

The facade also exposes the fake-only seed(), failRenewalOf() and every assert\* method once Certificates::fake() is active (see Testing). The manager is macroable, so your own methods show up on the facade too (see Extending).

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/certificates-for-laravel.md)
