json([ 'status' => 'ok', 'timestamp' => now()->toIso8601String(), 'version' => 'v1', ]); })->middleware('throttle:60,1')->name('api.health'); Route::get('/ping', function () { return response('pong', 200); })->middleware('throttle:60,1')->name('api.ping'); // CORS preflight for external admin dashboard or services Route::options('/{any}', function () { return response()->noContent(204); })->where('any', '.*'); $registerExternalApi = function () { // Read endpoints Route::get('/bonuses', [BonusApiController::class, 'index'])->middleware('throttle:60,1'); Route::get('/bonuses/{id}', [BonusApiController::class, 'show'])->whereNumber('id')->middleware('throttle:60,1'); // Mutating endpoints (stricter throttle) Route::post('/bonuses', [BonusApiController::class, 'store'])->middleware('throttle:20,1'); Route::patch('/bonuses/{id}', [BonusApiController::class, 'update'])->whereNumber('id')->middleware('throttle:20,1'); Route::delete('/bonuses/{id}', [BonusApiController::class, 'destroy'])->whereNumber('id')->middleware('throttle:20,1'); // Moderation API for user restrictions (token auth inside controller) Route::get('/users/{id}/restrictions', [UserRestrictionApiController::class, 'listForUser'])->whereNumber('id')->middleware('throttle:60,1'); Route::get('/users/{id}/restrictions/check', [UserRestrictionApiController::class, 'checkForUser'])->whereNumber('id')->middleware('throttle:60,1'); Route::post('/users/{id}/restrictions', [UserRestrictionApiController::class, 'createForUser'])->whereNumber('id')->middleware('throttle:20,1'); Route::post('/users/{id}/restrictions/upsert', [UserRestrictionApiController::class, 'upsertForUser'])->whereNumber('id')->middleware('throttle:20,1'); Route::patch('/restrictions/{id}', [UserRestrictionApiController::class, 'update'])->whereNumber('id')->middleware('throttle:20,1'); Route::delete('/restrictions/{id}', [UserRestrictionApiController::class, 'destroy'])->whereNumber('id')->middleware('throttle:20,1'); // External Vault API (token auth inside controller) Route::get('/users/{id}/vault', [VaultApiController::class, 'showForUser'])->whereNumber('id')->middleware('throttle:60,1'); Route::post('/users/{id}/vault/deposit', [VaultApiController::class, 'depositForUser'])->whereNumber('id')->middleware('throttle:20,1'); Route::post('/users/{id}/vault/withdraw', [VaultApiController::class, 'withdrawForUser'])->whereNumber('id')->middleware('throttle:20,1'); }; // NOWPayments IPN webhook (public). Note: The API middleware group has CSRF disabled by default. Route::post('/webhooks/nowpayments', [\App\Http\Controllers\NowPaymentsWebhookController::class, '__invoke']) ->middleware('throttle:60,1') ->name('api.webhooks.nowpayments'); // BetiX Originals: session-ended webhook (public, HMAC-verified inside controller) Route::post('/betix/session-ended', [\App\Http\Controllers\BetiXWebhookController::class, 'sessionEnded']) ->middleware('throttle:120,1') ->name('api.webhooks.betix'); // BetiX Originals: per-round balance update (public, HMAC-verified inside controller) Route::post('/betix/round', [\App\Http\Controllers\BetiXWebhookController::class, 'roundUpdate']) ->middleware('throttle:600,1') ->name('api.webhooks.betix.round'); // Unversioned (backward compatibility) Route::group([], $registerExternalApi); // Versioned alias Route::prefix('v1')->group($registerExternalApi);