Files
Mark Gregory 2b949cb354 phases 9
* Versioned REST API under /api/v1
* Published Pages API
* Published Blog API
* Published News API
* Secure bearer API tokens
* SHA-256 token storage
* Token abilities
* Token expiry and revocation
* Token usage tracking
* Webhook subscriptions
* Site-specific webhooks
* HMAC-SHA256 webhook signatures
* Webhook delivery history
* Failure tracking
* OpenAPI 3.1 JSON documentation
* API administration screen
* Administration navigation
* API permissions
* Module registration
* Feature tests
2026-07-24 12:09:36 +01:00

2 lines
2.8 KiB
PHP

<x-layouts.app :title="__('API & Webhooks')"><div class="space-y-8"><div><h1 class="text-2xl font-semibold">{{ __('API & Webhooks') }}</h1><p class="text-sm text-zinc-500">{{ __('Manage headless access, bearer tokens and webhook subscriptions.') }}</p></div>@if(session('status'))<flux:callout variant="success">{{ session('status') }}</flux:callout>@endif @if(session('api_token'))<flux:callout variant="warning"><strong>{{ __('Copy this token now') }}</strong><div class="mt-2 break-all font-mono">{{ session('api_token') }}</div></flux:callout>@endif<div class="grid gap-6 xl:grid-cols-2"><flux:card><h2 class="text-lg font-semibold">{{ __('Create token') }}</h2><form method="POST" action="{{ route('administration.api.tokens.store') }}" class="mt-4 space-y-4">@csrf<flux:input name="name" :label="__('Name')" required/><flux:input name="abilities" :label="__('Abilities')" value="content.read"/><flux:input name="expires_at" type="datetime-local" :label="__('Expires at')"/><flux:button type="submit" variant="primary">{{ __('Create') }}</flux:button></form></flux:card><flux:card><h2 class="text-lg font-semibold">{{ __('Create webhook') }}</h2><form method="POST" action="{{ route('administration.api.webhooks.store') }}" class="mt-4 space-y-4">@csrf<flux:input name="name" :label="__('Name')" required/><flux:input name="url" type="url" :label="__('URL')" required/><flux:input name="events" :label="__('Events')" value="content.published"/><flux:input name="site_id" type="number" :label="__('Site ID')"/><flux:button type="submit" variant="primary">{{ __('Create') }}</flux:button></form></flux:card></div><flux:card><div class="flex justify-between"><h2 class="text-lg font-semibold">{{ __('Tokens') }}</h2><a class="underline" href="{{ route('api.v1.openapi') }}">OpenAPI JSON</a></div>@forelse($tokens as $token)<div class="flex justify-between border-b py-3"><div>{{ $token->name }} <span class="text-sm text-zinc-500">{{ implode(', ', $token->abilities ?? []) }}</span></div><form method="POST" action="{{ route('administration.api.tokens.destroy',$token) }}">@csrf @method('DELETE')<flux:button size="sm" variant="danger">{{ __('Revoke') }}</flux:button></form></div>@empty<p class="py-4 text-zinc-500">{{ __('No tokens.') }}</p>@endforelse{{ $tokens->links() }}</flux:card><flux:card><h2 class="text-lg font-semibold">{{ __('Webhooks') }}</h2>@forelse($webhooks as $webhook)<div class="flex justify-between border-b py-3"><div>{{ $webhook->name }} <span class="text-sm text-zinc-500">{{ $webhook->url }}</span></div><form method="POST" action="{{ route('administration.api.webhooks.destroy',$webhook) }}">@csrf @method('DELETE')<flux:button size="sm" variant="danger">{{ __('Delete') }}</flux:button></form></div>@empty<p class="py-4 text-zinc-500">{{ __('No webhooks.') }}</p>@endforelse{{ $webhooks->links() }}</flux:card></div></x-layouts.app>