A visitor who walks into an office building without a badge could be anyone — no one at the front desk can say who they are or which floors they're allowed on. A visitor badge tied to a specific person, scanned at the door, lets the building attribute every entry to someone and revoke just that one badge if it's ever lost. An API key does the same job for a caller hitting an endpoint: it turns an anonymous request into an attributable, individually revocable one.
Every payment gateway, shipping carrier, and third-party package I integrated into Magento at Infracommerce identified the calling store through its own client-specific credential, not a shared anonymous one — that's what let the provider attribute usage, apply per-merchant limits, and revoke one client's access without touching every other store using the same integration module. Working across 10+ Infracommerce clients, each with its own set of these integrations, made that attribution model feel less like an abstract security nicety and more like a basic operational necessity.
Trade-off: once a caller has a key, someone has to manage its whole lifecycle — issuing it, rotating it, revoking it if it leaks — client identification stops being a design decision and becomes an ongoing operational responsibility.
Before
Route::get('/api/v1/reports', [ReportController::class, 'index']);
// any caller can hit this — no way to tell who,
// and no way to shut just one client offAfter
Route::middleware('auth.apikey')
->get('/api/v1/reports', [ReportController::class, 'index']);
class AuthenticateApiKey
{
public function handle(Request $request, Closure $next): mixed
{
$client = ApiClient::whereKey($request->header('X-Api-Key'))
->firstOrFail();
return $next($request);
}
}