runet-id/api-client
A Laravel/PHP client for the Runet-ID API that simplifies authentication and requests with a clean, configurable wrapper and typed responses for domain and registrar data. Add Runet-ID services to your app quickly using expressive methods and Laravel-friendly setup.
Install via Composer and confirm the package resolves against your PHP/Laravel version before writing any code — this client hasn't been released since March 2021, so check composer.json for the constraint it expects:
composer require runet-id/api-client
Where to look first, in this order:
README.md — likely Russian-language, but it's the only "documentation" the package ships.src/ — find the main client class and the resource/API-group classes (domains, IPs, AS numbers, organizations). The public methods on those classes are the API surface you'll use.tests/ — for a low-star, low-maintenance package, tests are often the most accurate contract description.First use case: checking whether a .ru / .рф / .su domain is registered, delegated, or free. That's the bread-and-butter query for registrars, domain-parking tools, and brand-protection services.
Minimal bootstrap (adapt names to what you find in src/):
$client = new RunetId\ApiClient\Client([
'token' => config('services.runet_id.token'),
]);
$info = $client->domains()->get('example.ru');
Get the token from your RU-CENTER / RUNET-ID account portal — the client authenticates with a per-user API key, not OAuth.
Wrap it in a service, immediately. With 0 stars and 0 dependents, treat this as a frozen, lightly-verified dependency. Don't scatter raw client calls through controllers. Build a DomainLookupService that takes the client through constructor injection, normalizes responses into your own DTOs, and handles exceptions in one place. When you eventually fork the package (likely), only this service changes.
Cache aggressively. RUNET-ID data changes on the timescale of days, not seconds. Registration, delegation, registrar assignment, and IP allocation are all stable. A 5-minute to 1-hour cache keyed by the queried identifier is almost mandatory — both for latency and to stay off rate limits.
Normalize IDN at the service boundary. .рф and mixed-script domains need idn_to_ascii() before the call. Keep the original Cyrillic string for display; convert to punycode only when talking to the API.
Bulk checks belong in a queue with concurrency limits. Don't foreach over thousands of domains synchronously. If the API supports batching (check the resource class), use it; otherwise fan out with a bounded worker pool and a shared rate limiter.
Treat error semantics as a policy, not an afterthought. Route every outcome through a small set of your own exceptions:
DomainNotFoundException — normal business outcome (domain is free)AuthenticationException — config/credential problem, page opsRateLimitedException — retry with backoffUpstreamException — retry, then alertLaravel integration tips:
config/services.php.RateLimiter facade before the client to enforce a token-bucket upstream-wide.The package is stale. A 2021 release means pre-PSR-18 conventions in places and possibly a hard-coded Guzzle dependency. Pin the version explicitly and be ready to fork and vendor it. Don't assume it works unchanged on PHP 8.3+.
"Not found" is ambiguous. Depending on how the resource class is written, a free domain might come back as an exception, a null, or an empty DTO. Test the not-found path against the live API once, before you build on it — this is the single most likely place to get burned.
IDN and Cyrillic edge cases. The API expects punycode; your users type Cyrillic. Homograph attacks matter if you use this for availability checks (.рф is a known target). Also watch for .su — different registry rules, sometimes different result shapes.
Rate limits are often undocumented. Measure your own request rate and impose a limiter regardless of what the README says. Treat HTTP 429 as a first-class, retryable failure.
Set aggressive timeouts. Default Guzzle timeouts will happily hang a queue worker for the full connection timeout. Set connect_timeout to ~2s and timeout to ~5s.
Secrets. Never commit the token. Read from env() via config/services.php; rotate anything that leaks — RUNET-ID tracks per-key usage and can throttle a compromised key.
The HTTP client is the real extension point. Most PHP API clients of this vintage let you inject a PSR-18 or Guzzle client. Use that for middleware — logging, retries, tracing, circuit-breaking — rather than wrapping every call site.
Snapshot for history. The API is a live view, not an event stream. If you need to know when a domain changed status, store the responses yourself; don't expect the client to page through historical data.
Testing strategy. Snapshot a handful of real responses once into fixtures, then build a fake client that returns them. This gives you fast, deterministic tests and a record of what the upstream actually returned the day you integrated it — invaluable when the package inevitably breaks.
How can I help you explore Laravel packages today?