fix: replace CDN Alpine with Flux directives, rebrand API portal
- Remove CDN Alpine.js from layout (conflicted with Flux's bundled Alpine)
- Add @fluxAppearance and @fluxScripts for proper Flux UI rendering
- Replace all hardcoded "Host UK" with config('core.app.name')
- Migrate colour scheme from slate to zinc, blue to cyan (match MCP portal)
- Rewrite index/reference/quickstart with brain/score API endpoints
- Fix broken route('api.guides.biolinks') references causing 500 errors
- Replace api.host.uk.com URLs with api.lthn.ai
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e709545db1
commit
774ecae403
14 changed files with 592 additions and 739 deletions
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Host UK API Documentation</title>
|
||||
<title>{{ config('core.app.name', 'Core PHP') }} API Documentation</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
|
||||
<style>
|
||||
html {
|
||||
|
|
@ -72,10 +72,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5" />
|
||||
</svg>
|
||||
Host UK API
|
||||
{{ config('core.app.name', 'Core PHP') }} API
|
||||
</h1>
|
||||
<nav class="api-header-links">
|
||||
<a href="{{ config('app.url') }}">Host UK</a>
|
||||
<a href="{{ config('app.url') }}">{{ config('core.app.name', 'Core PHP') }}</a>
|
||||
<a href="/openapi.json" target="_blank">OpenAPI JSON</a>
|
||||
<a href="{{ str_replace('api.', 'mcp.', request()->getSchemeAndHttpHost()) }}">MCP Portal</a>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -6,32 +6,32 @@
|
|||
<div class="flex">
|
||||
|
||||
{{-- Sidebar --}}
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-slate-200 dark:border-slate-800">
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-zinc-200 dark:border-zinc-800">
|
||||
<div class="h-full px-4 py-8 overflow-y-auto no-scrollbar">
|
||||
<nav>
|
||||
<ul class="space-y-2">
|
||||
<li>
|
||||
<a href="#overview" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#overview" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Overview
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#api-keys" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#api-keys" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
API Keys
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#using-keys" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#using-keys" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Using API Keys
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#scopes" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#scopes" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Scopes
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#security" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#security" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Security Best Practices
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -47,35 +47,35 @@
|
|||
{{-- Breadcrumb --}}
|
||||
<nav class="mb-8">
|
||||
<ol class="flex items-center gap-2 text-sm">
|
||||
<li><a href="{{ route('api.guides') }}" class="text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">Guides</a></li>
|
||||
<li class="text-slate-400">/</li>
|
||||
<li class="text-slate-800 dark:text-slate-200">Authentication</li>
|
||||
<li><a href="{{ route('api.guides') }}" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200">Guides</a></li>
|
||||
<li class="text-zinc-400">/</li>
|
||||
<li class="text-zinc-800 dark:text-zinc-200">Authentication</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<h1 class="h1 mb-4 text-slate-800 dark:text-slate-100">Authentication</h1>
|
||||
<p class="text-xl text-slate-600 dark:text-slate-400 mb-12">
|
||||
<h1 class="h1 mb-4 text-zinc-800 dark:text-zinc-100">Authentication</h1>
|
||||
<p class="text-xl text-zinc-600 dark:text-zinc-400 mb-12">
|
||||
Learn how to authenticate your API requests using API keys.
|
||||
</p>
|
||||
|
||||
{{-- Overview --}}
|
||||
<section id="overview" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Overview</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Overview</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
The API uses API keys for authentication. Each API key is scoped to a specific workspace and has configurable permissions.
|
||||
</p>
|
||||
<p class="text-slate-600 dark:text-slate-400">
|
||||
API keys are prefixed with <code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-sm">hk_</code> to make them easily identifiable.
|
||||
<p class="text-zinc-600 dark:text-zinc-400">
|
||||
API keys are prefixed with <code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-sm">hk_</code> to make them easily identifiable.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{{-- API Keys --}}
|
||||
<section id="api-keys" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">API Keys</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">API Keys</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
To create an API key:
|
||||
</p>
|
||||
<ol class="list-decimal list-inside space-y-2 text-slate-600 dark:text-slate-400 mb-6">
|
||||
<ol class="list-decimal list-inside space-y-2 text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
<li>Log in to your account</li>
|
||||
<li>Navigate to <strong>Settings → API Keys</strong></li>
|
||||
<li>Click <strong>Create API Key</strong></li>
|
||||
|
|
@ -98,59 +98,59 @@
|
|||
|
||||
{{-- Using Keys --}}
|
||||
<section id="using-keys" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Using API Keys</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
Include your API key in the <code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-sm">Authorization</code> header as a Bearer token:
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Using API Keys</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Include your API key in the <code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-sm">Authorization</code> header as a Bearer token:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">HTTP Header</span>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">HTTP Header</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300">Authorization: Bearer hk_your_api_key_here</code></pre>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300">Authorization: Bearer hk_your_api_key_here</code></pre>
|
||||
</div>
|
||||
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Example request with cURL:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">cURL</span>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">cURL</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-teal-400">curl</span> <span class="text-slate-500">--request</span> GET \
|
||||
<span class="text-slate-500">--url</span> <span class="text-amber-400">'https://api.host.uk.com/api/v1/bio'</span> \
|
||||
<span class="text-slate-500">--header</span> <span class="text-amber-400">'Authorization: Bearer hk_your_api_key'</span></code></pre>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-teal-400">curl</span> <span class="text-zinc-500">--request</span> GET \
|
||||
<span class="text-zinc-500">--url</span> <span class="text-amber-400">'https://api.lthn.ai/v1/brain/recall'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Authorization: Bearer hk_your_api_key'</span></code></pre>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{-- Scopes --}}
|
||||
<section id="scopes" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Scopes</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Scopes</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
API keys can have different scopes to limit their permissions:
|
||||
</p>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-slate-200 dark:border-slate-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Scope</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Description</th>
|
||||
<tr class="border-b border-zinc-200 dark:border-zinc-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Scope</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||
<tbody class="divide-y divide-zinc-200 dark:divide-zinc-700">
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">read</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Read access to resources (GET requests)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">read</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Read access to resources (GET requests)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">write</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Create and update resources (POST, PUT requests)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">write</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Create and update resources (POST, PUT requests)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">delete</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Delete resources (DELETE requests)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">delete</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Delete resources (DELETE requests)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -159,8 +159,8 @@
|
|||
|
||||
{{-- Security --}}
|
||||
<section id="security" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Security Best Practices</h2>
|
||||
<ul class="list-disc list-inside space-y-2 text-slate-600 dark:text-slate-400">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Security Best Practices</h2>
|
||||
<ul class="list-disc list-inside space-y-2 text-zinc-600 dark:text-zinc-400">
|
||||
<li>Never commit API keys to version control</li>
|
||||
<li>Use environment variables to store keys</li>
|
||||
<li>Rotate keys periodically</li>
|
||||
|
|
@ -171,12 +171,12 @@
|
|||
</section>
|
||||
|
||||
{{-- Next steps --}}
|
||||
<div class="flex items-center justify-between pt-8 border-t border-slate-200 dark:border-slate-700">
|
||||
<a href="{{ route('api.guides.quickstart') }}" class="text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200">
|
||||
<div class="flex items-center justify-between pt-8 border-t border-zinc-200 dark:border-zinc-700">
|
||||
<a href="{{ route('api.guides.quickstart') }}" class="text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200">
|
||||
← Quick Start
|
||||
</a>
|
||||
<a href="{{ route('api.guides.biolinks') }}" class="text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 font-medium">
|
||||
Managing Biolinks →
|
||||
<a href="{{ route('api.guides.webhooks') }}" class="text-cyan-600 hover:text-cyan-700 dark:hover:text-cyan-500 font-medium">
|
||||
Webhooks →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,32 +6,32 @@
|
|||
<div class="flex">
|
||||
|
||||
{{-- Sidebar --}}
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-slate-200 dark:border-slate-800">
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-zinc-200 dark:border-zinc-800">
|
||||
<div class="h-full px-4 py-8 overflow-y-auto no-scrollbar">
|
||||
<nav>
|
||||
<ul class="space-y-2">
|
||||
<li>
|
||||
<a href="#overview" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#overview" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Overview
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#http-codes" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#http-codes" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
HTTP Status Codes
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#error-format" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#error-format" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Error Format
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#common-errors" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#common-errors" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Common Errors
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#rate-limiting" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#rate-limiting" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Rate Limiting
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -47,73 +47,73 @@
|
|||
{{-- Breadcrumb --}}
|
||||
<nav class="mb-8">
|
||||
<ol class="flex items-center gap-2 text-sm">
|
||||
<li><a href="{{ route('api.guides') }}" class="text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">Guides</a></li>
|
||||
<li class="text-slate-400">/</li>
|
||||
<li class="text-slate-800 dark:text-slate-200">Error Handling</li>
|
||||
<li><a href="{{ route('api.guides') }}" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200">Guides</a></li>
|
||||
<li class="text-zinc-400">/</li>
|
||||
<li class="text-zinc-800 dark:text-zinc-200">Error Handling</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<h1 class="h1 mb-4 text-slate-800 dark:text-slate-100">Error Handling</h1>
|
||||
<p class="text-xl text-slate-600 dark:text-slate-400 mb-12">
|
||||
<h1 class="h1 mb-4 text-zinc-800 dark:text-zinc-100">Error Handling</h1>
|
||||
<p class="text-xl text-zinc-600 dark:text-zinc-400 mb-12">
|
||||
Understand API error codes and how to handle them gracefully.
|
||||
</p>
|
||||
|
||||
{{-- Overview --}}
|
||||
<section id="overview" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Overview</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Overview</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
The API uses conventional HTTP response codes to indicate success or failure. Codes in the 2xx range indicate success, 4xx indicate client errors, and 5xx indicate server errors.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{{-- HTTP Codes --}}
|
||||
<section id="http-codes" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">HTTP Status Codes</h2>
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">HTTP Status Codes</h2>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-slate-200 dark:border-slate-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Code</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Meaning</th>
|
||||
<tr class="border-b border-zinc-200 dark:border-zinc-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Code</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||
<tbody class="divide-y divide-zinc-200 dark:divide-zinc-700">
|
||||
<tr>
|
||||
<td class="py-3 px-4"><span class="px-2 py-1 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400 rounded text-xs font-medium">200</span></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Success - Request completed successfully</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Success - Request completed successfully</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><span class="px-2 py-1 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400 rounded text-xs font-medium">201</span></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Created - Resource was created successfully</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Created - Resource was created successfully</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><span class="px-2 py-1 bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400 rounded text-xs font-medium">400</span></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Bad Request - Invalid request parameters</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Bad Request - Invalid request parameters</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><span class="px-2 py-1 bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400 rounded text-xs font-medium">401</span></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Unauthorised - Invalid or missing API key</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Unauthorised - Invalid or missing API key</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><span class="px-2 py-1 bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400 rounded text-xs font-medium">403</span></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Forbidden - Insufficient permissions</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Forbidden - Insufficient permissions</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><span class="px-2 py-1 bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400 rounded text-xs font-medium">404</span></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Not Found - Resource doesn't exist</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Not Found - Resource doesn't exist</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><span class="px-2 py-1 bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400 rounded text-xs font-medium">422</span></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Unprocessable - Validation failed</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Unprocessable - Validation failed</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><span class="px-2 py-1 bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400 rounded text-xs font-medium">429</span></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Too Many Requests - Rate limit exceeded</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Too Many Requests - Rate limit exceeded</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><span class="px-2 py-1 bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400 rounded text-xs font-medium">500</span></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Server Error - Something went wrong on our end</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Server Error - Something went wrong on our end</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -122,13 +122,13 @@
|
|||
|
||||
{{-- Error Format --}}
|
||||
<section id="error-format" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Error Format</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Error Format</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Error responses include a JSON body with details:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300">{
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300">{
|
||||
<span class="text-blue-400">"message"</span>: <span class="text-green-400">"The given data was invalid."</span>,
|
||||
<span class="text-blue-400">"errors"</span>: {
|
||||
<span class="text-blue-400">"url"</span>: [
|
||||
|
|
@ -141,65 +141,65 @@
|
|||
|
||||
{{-- Common Errors --}}
|
||||
<section id="common-errors" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Common Errors</h2>
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Common Errors</h2>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="p-4 border border-slate-200 dark:border-slate-700 rounded-sm">
|
||||
<h4 class="font-medium text-slate-800 dark:text-slate-200 mb-2">Invalid API Key</h4>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
||||
<div class="p-4 border border-zinc-200 dark:border-zinc-700 rounded-sm">
|
||||
<h4 class="font-medium text-zinc-800 dark:text-zinc-200 mb-2">Invalid API Key</h4>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-2">
|
||||
Returned when the API key is missing, malformed, or revoked.
|
||||
</p>
|
||||
<code class="text-xs px-2 py-1 bg-slate-100 dark:bg-slate-800 rounded">401 Unauthorised</code>
|
||||
<code class="text-xs px-2 py-1 bg-zinc-100 dark:bg-zinc-800 rounded">401 Unauthorised</code>
|
||||
</div>
|
||||
|
||||
<div class="p-4 border border-slate-200 dark:border-slate-700 rounded-sm">
|
||||
<h4 class="font-medium text-slate-800 dark:text-slate-200 mb-2">Resource Not Found</h4>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
||||
<div class="p-4 border border-zinc-200 dark:border-zinc-700 rounded-sm">
|
||||
<h4 class="font-medium text-zinc-800 dark:text-zinc-200 mb-2">Resource Not Found</h4>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-2">
|
||||
The requested resource (biolink, workspace, etc.) doesn't exist or you don't have access.
|
||||
</p>
|
||||
<code class="text-xs px-2 py-1 bg-slate-100 dark:bg-slate-800 rounded">404 Not Found</code>
|
||||
<code class="text-xs px-2 py-1 bg-zinc-100 dark:bg-zinc-800 rounded">404 Not Found</code>
|
||||
</div>
|
||||
|
||||
<div class="p-4 border border-slate-200 dark:border-slate-700 rounded-sm">
|
||||
<h4 class="font-medium text-slate-800 dark:text-slate-200 mb-2">Validation Failed</h4>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
||||
<div class="p-4 border border-zinc-200 dark:border-zinc-700 rounded-sm">
|
||||
<h4 class="font-medium text-zinc-800 dark:text-zinc-200 mb-2">Validation Failed</h4>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-2">
|
||||
Request data failed validation. Check the <code>errors</code> object for specific fields.
|
||||
</p>
|
||||
<code class="text-xs px-2 py-1 bg-slate-100 dark:bg-slate-800 rounded">422 Unprocessable Entity</code>
|
||||
<code class="text-xs px-2 py-1 bg-zinc-100 dark:bg-zinc-800 rounded">422 Unprocessable Entity</code>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{-- Rate Limiting --}}
|
||||
<section id="rate-limiting" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Rate Limiting</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Rate Limiting</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
API requests are rate limited to ensure fair usage. Rate limit headers are included in all responses:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-4">
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300">X-RateLimit-Limit: 60
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-4">
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300">X-RateLimit-Limit: 60
|
||||
X-RateLimit-Remaining: 58
|
||||
X-RateLimit-Reset: 1705320000</code></pre>
|
||||
</div>
|
||||
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
When rate limited, you'll receive a 429 response. Wait until the reset timestamp before retrying.
|
||||
</p>
|
||||
|
||||
<div class="text-sm p-4 bg-slate-50 border border-slate-200 rounded-sm dark:bg-slate-800 dark:border-slate-700">
|
||||
<p class="text-slate-600 dark:text-slate-400">
|
||||
<div class="text-sm p-4 bg-zinc-50 border border-zinc-200 rounded-sm dark:bg-zinc-800 dark:border-zinc-700">
|
||||
<p class="text-zinc-600 dark:text-zinc-400">
|
||||
<strong>Tip:</strong> Implement exponential backoff in your retry logic. Start with a 1-second delay and double it with each retry, up to a maximum of 32 seconds.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{-- Next steps --}}
|
||||
<div class="flex items-center justify-between pt-8 border-t border-slate-200 dark:border-slate-700">
|
||||
<a href="{{ route('api.guides.webhooks') }}" class="text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200">
|
||||
<div class="flex items-center justify-between pt-8 border-t border-zinc-200 dark:border-zinc-700">
|
||||
<a href="{{ route('api.guides.webhooks') }}" class="text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200">
|
||||
← Webhooks
|
||||
</a>
|
||||
<a href="{{ route('api.reference') }}" class="text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 font-medium">
|
||||
<a href="{{ route('api.reference') }}" class="text-cyan-600 hover:text-cyan-700 dark:hover:text-cyan-500 font-medium">
|
||||
API Reference →
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
@section('content')
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 py-12">
|
||||
<div class="max-w-3xl">
|
||||
<h1 class="h2 mb-4 text-slate-800 dark:text-slate-100">Guides</h1>
|
||||
<p class="text-lg text-slate-600 dark:text-slate-400 mb-12">
|
||||
<h1 class="h2 mb-4 text-zinc-800 dark:text-zinc-100">Guides</h1>
|
||||
<p class="text-lg text-zinc-600 dark:text-zinc-400 mb-12">
|
||||
Step-by-step tutorials and best practices for integrating with the API.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -14,73 +14,51 @@
|
|||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
|
||||
{{-- Quick Start --}}
|
||||
<a href="{{ route('api.guides.quickstart') }}" class="group block p-6 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600 transition-colors">
|
||||
<a href="{{ route('api.guides.quickstart') }}" class="group block p-6 bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm hover:border-cyan-300 dark:hover:border-cyan-600 transition-colors">
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<div class="w-8 h-8 flex items-center justify-center bg-blue-100 dark:bg-blue-900/30 rounded-sm">
|
||||
<svg class="w-4 h-4 fill-blue-600" viewBox="0 0 16 16">
|
||||
<path d="M11.953 4.29a.5.5 0 0 0-.454-.292H6.14L6.984.62A.5.5 0 0 0 6.12.173l-6 7a.5.5 0 0 0 .379.825h5.359l-.844 3.38a.5.5 0 0 0 .864.445l6-7a.5.5 0 0 0 .075-.534Z" />
|
||||
</svg>
|
||||
<div class="w-8 h-8 flex items-center justify-center bg-cyan-100 dark:bg-cyan-900/30 rounded-sm">
|
||||
<i class="fa-solid fa-bolt text-cyan-600 text-sm"></i>
|
||||
</div>
|
||||
<span class="text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Getting Started</span>
|
||||
<span class="text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Getting Started</span>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-slate-800 dark:text-slate-100 group-hover:text-blue-600 dark:group-hover:text-blue-500">Quick Start</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">Get up and running with the API in under 5 minutes.</p>
|
||||
<h3 class="h4 mb-2 text-zinc-800 dark:text-zinc-100 group-hover:text-cyan-600 dark:group-hover:text-cyan-500">Quick Start</h3>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">Get up and running with the API in under 5 minutes.</p>
|
||||
</a>
|
||||
|
||||
{{-- Authentication --}}
|
||||
<a href="{{ route('api.guides.authentication') }}" class="group block p-6 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600 transition-colors">
|
||||
<a href="{{ route('api.guides.authentication') }}" class="group block p-6 bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm hover:border-cyan-300 dark:hover:border-cyan-600 transition-colors">
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<div class="w-8 h-8 flex items-center justify-center bg-amber-100 dark:bg-amber-900/30 rounded-sm">
|
||||
<svg class="w-4 h-4 fill-amber-600" viewBox="0 0 16 16">
|
||||
<path d="M8 1a4 4 0 0 0-4 4v3H3a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1h-1V5a4 4 0 0 0-4-4zm2 7V5a2 2 0 1 0-4 0v3h4z"/>
|
||||
</svg>
|
||||
<i class="fa-solid fa-key text-amber-600 text-sm"></i>
|
||||
</div>
|
||||
<span class="text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Security</span>
|
||||
<span class="text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Security</span>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-slate-800 dark:text-slate-100 group-hover:text-blue-600 dark:group-hover:text-blue-500">Authentication</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">Learn how to authenticate your API requests using API keys.</p>
|
||||
</a>
|
||||
|
||||
{{-- QR Codes --}}
|
||||
<a href="{{ route('api.guides.qrcodes') }}" class="group block p-6 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600 transition-colors">
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<div class="w-8 h-8 flex items-center justify-center bg-teal-100 dark:bg-teal-900/30 rounded-sm">
|
||||
<svg class="w-4 h-4 fill-teal-600" viewBox="0 0 16 16">
|
||||
<path d="M2 3a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3zm2 2V4h1v1H4z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Core</span>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-slate-800 dark:text-slate-100 group-hover:text-blue-600 dark:group-hover:text-blue-500">QR Code Generation</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">Generate customisable QR codes with colours, logos, and formats.</p>
|
||||
<h3 class="h4 mb-2 text-zinc-800 dark:text-zinc-100 group-hover:text-cyan-600 dark:group-hover:text-cyan-500">Authentication</h3>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">Learn how to authenticate your API requests using API keys.</p>
|
||||
</a>
|
||||
|
||||
{{-- Webhooks --}}
|
||||
<a href="{{ route('api.guides.webhooks') }}" class="group block p-6 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600 transition-colors">
|
||||
<a href="{{ route('api.guides.webhooks') }}" class="group block p-6 bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm hover:border-cyan-300 dark:hover:border-cyan-600 transition-colors">
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<div class="w-8 h-8 flex items-center justify-center bg-rose-100 dark:bg-rose-900/30 rounded-sm">
|
||||
<svg class="w-4 h-4 fill-rose-600" viewBox="0 0 16 16">
|
||||
<path d="M8.94 1.5a.75.75 0 0 0-1.06 0L7 2.38 6.12 1.5a.75.75 0 0 0-1.06 1.06l.88.88-.88.88a.75.75 0 1 0 1.06 1.06L7 4.5l.88.88a.75.75 0 1 0 1.06-1.06l-.88-.88.88-.88a.75.75 0 0 0 0-1.06z"/>
|
||||
</svg>
|
||||
<i class="fa-solid fa-satellite-dish text-rose-600 text-sm"></i>
|
||||
</div>
|
||||
<span class="text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Advanced</span>
|
||||
<span class="text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Advanced</span>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-slate-800 dark:text-slate-100 group-hover:text-blue-600 dark:group-hover:text-blue-500">Webhooks</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">Receive real-time notifications for events in your workspace.</p>
|
||||
<h3 class="h4 mb-2 text-zinc-800 dark:text-zinc-100 group-hover:text-cyan-600 dark:group-hover:text-cyan-500">Webhooks</h3>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">Receive real-time notifications for events in your workspace.</p>
|
||||
</a>
|
||||
|
||||
{{-- Error Handling --}}
|
||||
<a href="{{ route('api.guides.errors') }}" class="group block p-6 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600 transition-colors">
|
||||
<a href="{{ route('api.guides.errors') }}" class="group block p-6 bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm hover:border-cyan-300 dark:hover:border-cyan-600 transition-colors">
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<div class="w-8 h-8 flex items-center justify-center bg-slate-100 dark:bg-slate-700 rounded-sm">
|
||||
<svg class="w-4 h-4 fill-slate-600 dark:fill-slate-400" viewBox="0 0 16 16">
|
||||
<path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 3a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/>
|
||||
</svg>
|
||||
<div class="w-8 h-8 flex items-center justify-center bg-zinc-100 dark:bg-zinc-700 rounded-sm">
|
||||
<i class="fa-solid fa-triangle-exclamation text-zinc-600 dark:text-zinc-400 text-sm"></i>
|
||||
</div>
|
||||
<span class="text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Reference</span>
|
||||
<span class="text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Reference</span>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-slate-800 dark:text-slate-100 group-hover:text-blue-600 dark:group-hover:text-blue-500">Error Handling</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">Understand API error codes and how to handle them gracefully.</p>
|
||||
<h3 class="h4 mb-2 text-zinc-800 dark:text-zinc-100 group-hover:text-cyan-600 dark:group-hover:text-cyan-500">Error Handling</h3>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">Understand API error codes and how to handle them gracefully.</p>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,32 +6,32 @@
|
|||
<div class="flex">
|
||||
|
||||
{{-- Sidebar --}}
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-slate-200 dark:border-slate-800">
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-zinc-200 dark:border-zinc-800">
|
||||
<div class="h-full px-4 py-8 overflow-y-auto no-scrollbar">
|
||||
<nav>
|
||||
<ul class="space-y-2">
|
||||
<li>
|
||||
<a href="#overview" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#overview" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Overview
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#biolink-qr" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#biolink-qr" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Biolink QR Codes
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#custom-qr" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#custom-qr" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Custom URL QR Codes
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#options" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#options" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Customisation Options
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#download" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#download" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Download Formats
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -47,24 +47,24 @@
|
|||
{{-- Breadcrumb --}}
|
||||
<nav class="mb-8">
|
||||
<ol class="flex items-center gap-2 text-sm">
|
||||
<li><a href="{{ route('api.guides') }}" class="text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">Guides</a></li>
|
||||
<li class="text-slate-400">/</li>
|
||||
<li class="text-slate-800 dark:text-slate-200">QR Code Generation</li>
|
||||
<li><a href="{{ route('api.guides') }}" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200">Guides</a></li>
|
||||
<li class="text-zinc-400">/</li>
|
||||
<li class="text-zinc-800 dark:text-zinc-200">QR Code Generation</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<h1 class="h1 mb-4 text-slate-800 dark:text-slate-100">QR Code Generation</h1>
|
||||
<p class="text-xl text-slate-600 dark:text-slate-400 mb-12">
|
||||
<h1 class="h1 mb-4 text-zinc-800 dark:text-zinc-100">QR Code Generation</h1>
|
||||
<p class="text-xl text-zinc-600 dark:text-zinc-400 mb-12">
|
||||
Generate customisable QR codes for your biolinks or any URL.
|
||||
</p>
|
||||
|
||||
{{-- Overview --}}
|
||||
<section id="overview" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Overview</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Overview</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
The API provides two ways to generate QR codes:
|
||||
</p>
|
||||
<ul class="list-disc list-inside space-y-2 text-slate-600 dark:text-slate-400">
|
||||
<ul class="list-disc list-inside space-y-2 text-zinc-600 dark:text-zinc-400">
|
||||
<li><strong>Biolink QR codes</strong> - Generate QR codes for your existing biolinks</li>
|
||||
<li><strong>Custom URL QR codes</strong> - Generate QR codes for any URL</li>
|
||||
</ul>
|
||||
|
|
@ -72,24 +72,24 @@
|
|||
|
||||
{{-- Biolink QR --}}
|
||||
<section id="biolink-qr" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Biolink QR Codes</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Biolink QR Codes</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Get QR code data for an existing biolink:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">cURL</span>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">cURL</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-teal-400">curl</span> <span class="text-slate-500">--request</span> GET \
|
||||
<span class="text-slate-500">--url</span> <span class="text-amber-400">'https://api.host.uk.com/api/v1/bio/1/qr'</span> \
|
||||
<span class="text-slate-500">--header</span> <span class="text-amber-400">'Authorization: Bearer YOUR_API_KEY'</span></code></pre>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-teal-400">curl</span> <span class="text-zinc-500">--request</span> GET \
|
||||
<span class="text-zinc-500">--url</span> <span class="text-amber-400">'https://api.lthn.ai/api/v1/bio/1/qr'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Authorization: Bearer YOUR_API_KEY'</span></code></pre>
|
||||
</div>
|
||||
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">Response:</p>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">Response:</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300">{
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300">{
|
||||
<span class="text-blue-400">"data"</span>: {
|
||||
<span class="text-blue-400">"svg"</span>: <span class="text-green-400">"<svg>...</svg>"</span>,
|
||||
<span class="text-blue-400">"url"</span>: <span class="text-green-400">"https://example.com/mypage"</span>
|
||||
|
|
@ -100,20 +100,20 @@
|
|||
|
||||
{{-- Custom QR --}}
|
||||
<section id="custom-qr" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Custom URL QR Codes</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Custom URL QR Codes</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Generate a QR code for any URL:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">cURL</span>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">cURL</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-teal-400">curl</span> <span class="text-slate-500">--request</span> POST \
|
||||
<span class="text-slate-500">--url</span> <span class="text-amber-400">'https://api.host.uk.com/api/v1/qr/generate'</span> \
|
||||
<span class="text-slate-500">--header</span> <span class="text-amber-400">'Authorization: Bearer YOUR_API_KEY'</span> \
|
||||
<span class="text-slate-500">--header</span> <span class="text-amber-400">'Content-Type: application/json'</span> \
|
||||
<span class="text-slate-500">--data</span> <span class="text-amber-400">'{
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-teal-400">curl</span> <span class="text-zinc-500">--request</span> POST \
|
||||
<span class="text-zinc-500">--url</span> <span class="text-amber-400">'https://api.lthn.ai/api/v1/qr/generate'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Authorization: Bearer YOUR_API_KEY'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Content-Type: application/json'</span> \
|
||||
<span class="text-zinc-500">--data</span> <span class="text-amber-400">'{
|
||||
"url": "https://example.com",
|
||||
"format": "svg",
|
||||
"size": 300
|
||||
|
|
@ -123,40 +123,40 @@
|
|||
|
||||
{{-- Options --}}
|
||||
<section id="options" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Customisation Options</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Customisation Options</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Available customisation parameters:
|
||||
</p>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-slate-200 dark:border-slate-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Parameter</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Type</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Description</th>
|
||||
<tr class="border-b border-zinc-200 dark:border-zinc-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Parameter</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Type</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||
<tbody class="divide-y divide-zinc-200 dark:divide-zinc-700">
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">format</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">string</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Output format: <code>svg</code> or <code>png</code></td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">format</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">string</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Output format: <code>svg</code> or <code>png</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">size</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">integer</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Size in pixels (100-2000)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">size</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">integer</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Size in pixels (100-2000)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">color</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">string</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Foreground colour (hex)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">color</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">string</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Foreground colour (hex)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">background</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">string</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Background colour (hex)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">background</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">string</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Background colour (hex)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -165,32 +165,32 @@
|
|||
|
||||
{{-- Download --}}
|
||||
<section id="download" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Download Formats</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Download Formats</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Download QR codes directly as image files:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">cURL</span>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">cURL</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-teal-400">curl</span> <span class="text-slate-500">--request</span> GET \
|
||||
<span class="text-slate-500">--url</span> <span class="text-amber-400">'https://api.host.uk.com/api/v1/bio/1/qr/download?format=png&size=500'</span> \
|
||||
<span class="text-slate-500">--header</span> <span class="text-amber-400">'Authorization: Bearer YOUR_API_KEY'</span> \
|
||||
<span class="text-slate-500">--output</span> <span class="text-amber-400">qrcode.png</span></code></pre>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-teal-400">curl</span> <span class="text-zinc-500">--request</span> GET \
|
||||
<span class="text-zinc-500">--url</span> <span class="text-amber-400">'https://api.lthn.ai/api/v1/bio/1/qr/download?format=png&size=500'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Authorization: Bearer YOUR_API_KEY'</span> \
|
||||
<span class="text-zinc-500">--output</span> <span class="text-amber-400">qrcode.png</span></code></pre>
|
||||
</div>
|
||||
|
||||
<p class="text-slate-600 dark:text-slate-400">
|
||||
<p class="text-zinc-600 dark:text-zinc-400">
|
||||
The response is binary image data with appropriate Content-Type header.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{{-- Next steps --}}
|
||||
<div class="flex items-center justify-between pt-8 border-t border-slate-200 dark:border-slate-700">
|
||||
<a href="{{ route('api.guides.biolinks') }}" class="text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200">
|
||||
← Managing Biolinks
|
||||
<div class="flex items-center justify-between pt-8 border-t border-zinc-200 dark:border-zinc-700">
|
||||
<a href="{{ route('api.guides.authentication') }}" class="text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200">
|
||||
← Authentication
|
||||
</a>
|
||||
<a href="{{ route('api.guides.webhooks') }}" class="text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 font-medium">
|
||||
<a href="{{ route('api.guides.webhooks') }}" class="text-cyan-600 hover:text-cyan-700 dark:hover:text-blue-500 font-medium">
|
||||
Webhooks →
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,32 +6,32 @@
|
|||
<div class="flex">
|
||||
|
||||
{{-- Sidebar --}}
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-slate-200 dark:border-slate-800">
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-zinc-200 dark:border-zinc-800">
|
||||
<div class="h-full px-4 py-8 overflow-y-auto no-scrollbar">
|
||||
<nav>
|
||||
<ul class="space-y-2">
|
||||
<li>
|
||||
<a href="#prerequisites" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#prerequisites" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Prerequisites
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#create-api-key" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#create-api-key" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Create an API Key
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#first-request" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#first-request" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Make Your First Request
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#create-biolink" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Create a Biolink
|
||||
<a href="#store-memory" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Store a Memory
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#next-steps" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#next-steps" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Next Steps
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -47,24 +47,24 @@
|
|||
{{-- Breadcrumb --}}
|
||||
<nav class="mb-8">
|
||||
<ol class="flex items-center gap-2 text-sm">
|
||||
<li><a href="{{ route('api.guides') }}" class="text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">Guides</a></li>
|
||||
<li class="text-slate-400">/</li>
|
||||
<li class="text-slate-800 dark:text-slate-200">Quick Start</li>
|
||||
<li><a href="{{ route('api.guides') }}" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200">Guides</a></li>
|
||||
<li class="text-zinc-400">/</li>
|
||||
<li class="text-zinc-800 dark:text-zinc-200">Quick Start</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<h1 class="h1 mb-4 text-slate-800 dark:text-slate-100">Quick Start</h1>
|
||||
<p class="text-xl text-slate-600 dark:text-slate-400 mb-12">
|
||||
<h1 class="h1 mb-4 text-zinc-800 dark:text-zinc-100">Quick Start</h1>
|
||||
<p class="text-xl text-zinc-600 dark:text-zinc-400 mb-12">
|
||||
Get up and running with the API in under 5 minutes.
|
||||
</p>
|
||||
|
||||
{{-- Prerequisites --}}
|
||||
<section id="prerequisites" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Prerequisites</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Prerequisites</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Before you begin, you'll need:
|
||||
</p>
|
||||
<ul class="list-disc list-inside space-y-2 text-slate-600 dark:text-slate-400 mb-4">
|
||||
<ul class="list-disc list-inside space-y-2 text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
<li>An account with API access</li>
|
||||
<li>A workspace (created automatically on signup)</li>
|
||||
<li>cURL or any HTTP client</li>
|
||||
|
|
@ -73,16 +73,16 @@
|
|||
|
||||
{{-- Create API Key --}}
|
||||
<section id="create-api-key" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Create an API Key</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Create an API Key</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Navigate to your workspace settings and create a new API key:
|
||||
</p>
|
||||
<ol class="list-decimal list-inside space-y-2 text-slate-600 dark:text-slate-400 mb-6">
|
||||
<li>Go to <strong>Settings → API Keys</strong></li>
|
||||
<ol class="list-decimal list-inside space-y-2 text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
<li>Go to <strong>Settings → API Keys</strong></li>
|
||||
<li>Click <strong>Create API Key</strong></li>
|
||||
<li>Give it a name (e.g., "Development")</li>
|
||||
<li>Select the scopes you need (read, write, delete)</li>
|
||||
<li>Copy the key - it won't be shown again!</li>
|
||||
<li>Copy the key — it won't be shown again!</li>
|
||||
</ol>
|
||||
|
||||
{{-- Note box --}}
|
||||
|
|
@ -100,88 +100,87 @@
|
|||
|
||||
{{-- First Request --}}
|
||||
<section id="first-request" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Make Your First Request</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
Let's verify your API key by listing your workspaces:
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Make Your First Request</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Let's verify your API key by searching agent memories:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">cURL</span>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">cURL</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-teal-400">curl</span> <span class="text-slate-500">--request</span> GET \
|
||||
<span class="text-slate-500">--url</span> <span class="text-amber-400">'https://api.host.uk.com/api/v1/workspaces/current'</span> \
|
||||
<span class="text-slate-500">--header</span> <span class="text-amber-400">'Authorization: Bearer YOUR_API_KEY'</span></code></pre>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-teal-400">curl</span> <span class="text-zinc-500">--request</span> POST \
|
||||
<span class="text-zinc-500">--url</span> <span class="text-amber-400">'https://api.lthn.ai/v1/brain/recall'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Authorization: Bearer hk_your_api_key'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Content-Type: application/json'</span> \
|
||||
<span class="text-zinc-500">--data</span> <span class="text-amber-400">'{"query": "hello world"}'</span></code></pre>
|
||||
</div>
|
||||
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
You should receive a response like:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">Response</span>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">Response</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300">{
|
||||
<span class="text-blue-400">"data"</span>: {
|
||||
<span class="text-blue-400">"id"</span>: <span class="text-amber-400">1</span>,
|
||||
<span class="text-blue-400">"name"</span>: <span class="text-green-400">"My Workspace"</span>,
|
||||
<span class="text-blue-400">"slug"</span>: <span class="text-green-400">"my-workspace-abc123"</span>,
|
||||
<span class="text-blue-400">"is_active"</span>: <span class="text-purple-400">true</span>
|
||||
}
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300">{
|
||||
<span class="text-blue-400">"memories"</span>: [],
|
||||
<span class="text-blue-400">"scores"</span>: {}
|
||||
}</code></pre>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{-- Create Biolink --}}
|
||||
<section id="create-biolink" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Create a Biolink</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
Now let's create your first biolink programmatically:
|
||||
{{-- Store Memory --}}
|
||||
<section id="store-memory" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Store a Memory</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Now let's store your first memory in the brain:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">cURL</span>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-4">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">cURL</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-teal-400">curl</span> <span class="text-slate-500">--request</span> POST \
|
||||
<span class="text-slate-500">--url</span> <span class="text-amber-400">'https://api.host.uk.com/api/v1/bio'</span> \
|
||||
<span class="text-slate-500">--header</span> <span class="text-amber-400">'Authorization: Bearer YOUR_API_KEY'</span> \
|
||||
<span class="text-slate-500">--header</span> <span class="text-amber-400">'Content-Type: application/json'</span> \
|
||||
<span class="text-slate-500">--data</span> <span class="text-amber-400">'{
|
||||
"url": "mypage",
|
||||
"type": "biolink"
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-teal-400">curl</span> <span class="text-zinc-500">--request</span> POST \
|
||||
<span class="text-zinc-500">--url</span> <span class="text-amber-400">'https://api.lthn.ai/v1/brain/remember'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Authorization: Bearer hk_your_api_key'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Content-Type: application/json'</span> \
|
||||
<span class="text-zinc-500">--data</span> <span class="text-amber-400">'{
|
||||
"content": "Go uses structural typing",
|
||||
"type": "fact",
|
||||
"tags": ["go", "typing"]
|
||||
}'</span></code></pre>
|
||||
</div>
|
||||
|
||||
<p class="text-slate-600 dark:text-slate-400">
|
||||
This creates a new biolink page at your configured short URL.
|
||||
<p class="text-zinc-600 dark:text-zinc-400">
|
||||
This stores a fact in the vector database. You can then recall it with a semantic query.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{{-- Next Steps --}}
|
||||
<section id="next-steps" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Next Steps</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-6">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Next Steps</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
Now that you've made your first API calls, explore more:
|
||||
</p>
|
||||
|
||||
<div class="grid sm:grid-cols-2 gap-4">
|
||||
<a href="{{ route('api.guides.biolinks') }}" class="p-4 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600">
|
||||
<h3 class="font-medium text-slate-800 dark:text-slate-200 mb-1">Managing Biolinks</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">Add blocks, update settings, and customise themes.</p>
|
||||
<a href="{{ route('api.guides.authentication') }}" class="p-4 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm hover:border-cyan-300 dark:hover:border-cyan-600">
|
||||
<h3 class="font-medium text-zinc-800 dark:text-zinc-200 mb-1">Authentication</h3>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">API key scopes, security best practices.</p>
|
||||
</a>
|
||||
<a href="{{ route('api.guides.qrcodes') }}" class="p-4 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600">
|
||||
<h3 class="font-medium text-slate-800 dark:text-slate-200 mb-1">QR Code Generation</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">Generate customised QR codes for your biolinks.</p>
|
||||
<a href="{{ route('api.reference') }}" class="p-4 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm hover:border-cyan-300 dark:hover:border-cyan-600">
|
||||
<h3 class="font-medium text-zinc-800 dark:text-zinc-200 mb-1">API Reference</h3>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">Complete documentation of all endpoints.</p>
|
||||
</a>
|
||||
<a href="{{ route('api.reference') }}" class="p-4 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600">
|
||||
<h3 class="font-medium text-slate-800 dark:text-slate-200 mb-1">API Reference</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">Complete documentation of all endpoints.</p>
|
||||
<a href="{{ route('api.guides.webhooks') }}" class="p-4 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm hover:border-cyan-300 dark:hover:border-cyan-600">
|
||||
<h3 class="font-medium text-zinc-800 dark:text-zinc-200 mb-1">Webhooks</h3>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">Receive real-time event notifications.</p>
|
||||
</a>
|
||||
<a href="{{ route('api.swagger') }}" class="p-4 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600">
|
||||
<h3 class="font-medium text-slate-800 dark:text-slate-200 mb-1">Swagger UI</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">Interactive API explorer with try-it-out.</p>
|
||||
<a href="{{ route('api.swagger') }}" class="p-4 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm hover:border-cyan-300 dark:hover:border-cyan-600">
|
||||
<h3 class="font-medium text-zinc-800 dark:text-zinc-200 mb-1">Swagger UI</h3>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">Interactive API explorer with try-it-out.</p>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -6,47 +6,47 @@
|
|||
<div class="flex">
|
||||
|
||||
{{-- Sidebar --}}
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-slate-200 dark:border-slate-800">
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-zinc-200 dark:border-zinc-800">
|
||||
<div class="h-full px-4 py-8 overflow-y-auto no-scrollbar">
|
||||
<nav>
|
||||
<ul class="space-y-2">
|
||||
<li>
|
||||
<a href="#overview" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#overview" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Overview
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#setup" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#setup" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Setup
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#events" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#events" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Event Types
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#payload" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#payload" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Payload Format
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#headers" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#headers" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Request Headers
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#verification" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#verification" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Signature Verification
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#retry-policy" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#retry-policy" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Retry Policy
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#best-practices" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
<a href="#best-practices" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Best Practices
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -62,24 +62,24 @@
|
|||
{{-- Breadcrumb --}}
|
||||
<nav class="mb-8">
|
||||
<ol class="flex items-center gap-2 text-sm">
|
||||
<li><a href="{{ route('api.guides') }}" class="text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">Guides</a></li>
|
||||
<li class="text-slate-400">/</li>
|
||||
<li class="text-slate-800 dark:text-slate-200">Webhooks</li>
|
||||
<li><a href="{{ route('api.guides') }}" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200">Guides</a></li>
|
||||
<li class="text-zinc-400">/</li>
|
||||
<li class="text-zinc-800 dark:text-zinc-200">Webhooks</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<h1 class="h1 mb-4 text-slate-800 dark:text-slate-100">Webhooks</h1>
|
||||
<p class="text-xl text-slate-600 dark:text-slate-400 mb-12">
|
||||
<h1 class="h1 mb-4 text-zinc-800 dark:text-zinc-100">Webhooks</h1>
|
||||
<p class="text-xl text-zinc-600 dark:text-zinc-400 mb-12">
|
||||
Receive real-time notifications for events in your workspace with cryptographically signed payloads.
|
||||
</p>
|
||||
|
||||
{{-- Overview --}}
|
||||
<section id="overview" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Overview</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Overview</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Webhooks allow your application to receive real-time HTTP callbacks when events occur in your workspace. Instead of polling the API, webhooks push data to your server as events happen.
|
||||
</p>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
All webhook requests are cryptographically signed using HMAC-SHA256, allowing you to verify that requests genuinely came from our platform and haven't been tampered with.
|
||||
</p>
|
||||
<div class="text-sm p-4 bg-amber-50 border border-amber-200 rounded-sm dark:bg-amber-900/20 dark:border-amber-800">
|
||||
|
|
@ -96,11 +96,11 @@
|
|||
|
||||
{{-- Setup --}}
|
||||
<section id="setup" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Setup</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Setup</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
To configure webhooks:
|
||||
</p>
|
||||
<ol class="list-decimal list-inside space-y-2 text-slate-600 dark:text-slate-400 mb-4">
|
||||
<ol class="list-decimal list-inside space-y-2 text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
<li>Go to <strong>Settings → Webhooks</strong> in your workspace</li>
|
||||
<li>Click <strong>Add Webhook</strong></li>
|
||||
<li>Enter your endpoint URL (must be HTTPS in production)</li>
|
||||
|
|
@ -121,51 +121,51 @@
|
|||
|
||||
{{-- Events --}}
|
||||
<section id="events" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Event Types</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Event Types</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Available webhook events:
|
||||
</p>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-slate-200 dark:border-slate-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Event</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Description</th>
|
||||
<tr class="border-b border-zinc-200 dark:border-zinc-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Event</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||
<tbody class="divide-y divide-zinc-200 dark:divide-zinc-700">
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">bio.created</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">A new biolink was created</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">bio.created</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">A new biolink was created</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">bio.updated</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">A biolink was updated</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">bio.updated</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">A biolink was updated</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">bio.deleted</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">A biolink was deleted</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">bio.deleted</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">A biolink was deleted</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">link.created</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">A new link was created</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">link.created</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">A new link was created</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">link.clicked</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">A link was clicked (high volume)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">link.clicked</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">A link was clicked (high volume)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">qrcode.created</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">A QR code was generated</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">qrcode.created</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">A QR code was generated</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">qrcode.scanned</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">A QR code was scanned (high volume)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">qrcode.scanned</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">A QR code was scanned (high volume)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">*</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Subscribe to all events (wildcard)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">*</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Subscribe to all events (wildcard)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -174,13 +174,13 @@
|
|||
|
||||
{{-- Payload --}}
|
||||
<section id="payload" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Payload Format</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Payload Format</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Webhook payloads are sent as JSON with a consistent structure:
|
||||
</p>
|
||||
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300">{
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300">{
|
||||
<span class="text-blue-400">"id"</span>: <span class="text-green-400">"evt_abc123xyz456"</span>,
|
||||
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"bio.created"</span>,
|
||||
<span class="text-blue-400">"created_at"</span>: <span class="text-green-400">"2024-01-15T10:30:00Z"</span>,
|
||||
|
|
@ -196,39 +196,39 @@
|
|||
|
||||
{{-- Headers --}}
|
||||
<section id="headers" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Request Headers</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Request Headers</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Every webhook request includes the following headers:
|
||||
</p>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-slate-200 dark:border-slate-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Header</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Description</th>
|
||||
<tr class="border-b border-zinc-200 dark:border-zinc-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Header</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||
<tbody class="divide-y divide-zinc-200 dark:divide-zinc-700">
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">X-Webhook-Signature</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">HMAC-SHA256 signature for verification</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">X-Webhook-Signature</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">HMAC-SHA256 signature for verification</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">X-Webhook-Timestamp</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Unix timestamp when the webhook was sent</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">X-Webhook-Timestamp</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Unix timestamp when the webhook was sent</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">X-Webhook-Event</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">The event type (e.g., <code>bio.created</code>)</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">X-Webhook-Event</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">The event type (e.g., <code>bio.created</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">X-Webhook-Id</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Unique delivery ID for idempotency</td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">X-Webhook-Id</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Unique delivery ID for idempotency</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-800 rounded text-xs">Content-Type</code></td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Always <code>application/json</code></td>
|
||||
<td class="py-3 px-4"><code class="px-1.5 py-0.5 bg-zinc-100 dark:bg-zinc-800 rounded text-xs">Content-Type</code></td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Always <code>application/json</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -237,13 +237,13 @@
|
|||
|
||||
{{-- Verification --}}
|
||||
<section id="verification" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Signature Verification</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Signature Verification</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
To verify a webhook signature, compute the HMAC-SHA256 of the timestamp concatenated with the raw request body using your webhook secret. The signature includes the timestamp to prevent replay attacks.
|
||||
</p>
|
||||
|
||||
<h3 class="h4 mb-3 text-slate-800 dark:text-slate-100">Verification Algorithm</h3>
|
||||
<ol class="list-decimal list-inside space-y-2 text-slate-600 dark:text-slate-400 mb-6">
|
||||
<h3 class="h4 mb-3 text-zinc-800 dark:text-zinc-100">Verification Algorithm</h3>
|
||||
<ol class="list-decimal list-inside space-y-2 text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
<li>Extract <code>X-Webhook-Signature</code> and <code>X-Webhook-Timestamp</code> headers</li>
|
||||
<li>Concatenate: <code>timestamp + "." + raw_request_body</code></li>
|
||||
<li>Compute: <code>HMAC-SHA256(concatenated_string, your_webhook_secret)</code></li>
|
||||
|
|
@ -252,75 +252,75 @@
|
|||
</ol>
|
||||
|
||||
{{-- PHP Example --}}
|
||||
<h3 class="h4 mb-3 text-slate-800 dark:text-slate-100">PHP</h3>
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">webhook-handler.php</span>
|
||||
<h3 class="h4 mb-3 text-zinc-800 dark:text-zinc-100">PHP</h3>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">webhook-handler.php</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-purple-400"><?php</span>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-purple-400"><?php</span>
|
||||
|
||||
<span class="text-slate-500">// Get request data</span>
|
||||
<span class="text-zinc-500">// Get request data</span>
|
||||
<span class="text-purple-400">$payload</span> = <span class="text-teal-400">file_get_contents</span>(<span class="text-green-400">'php://input'</span>);
|
||||
<span class="text-purple-400">$signature</span> = <span class="text-purple-400">$_SERVER</span>[<span class="text-green-400">'HTTP_X_WEBHOOK_SIGNATURE'</span>] ?? <span class="text-green-400">''</span>;
|
||||
<span class="text-purple-400">$timestamp</span> = <span class="text-purple-400">$_SERVER</span>[<span class="text-green-400">'HTTP_X_WEBHOOK_TIMESTAMP'</span>] ?? <span class="text-green-400">''</span>;
|
||||
<span class="text-purple-400">$secret</span> = <span class="text-teal-400">getenv</span>(<span class="text-green-400">'WEBHOOK_SECRET'</span>);
|
||||
|
||||
<span class="text-slate-500">// Verify timestamp (5 minute tolerance)</span>
|
||||
<span class="text-zinc-500">// Verify timestamp (5 minute tolerance)</span>
|
||||
<span class="text-purple-400">$tolerance</span> = <span class="text-amber-400">300</span>;
|
||||
<span class="text-pink-400">if</span> (<span class="text-teal-400">abs</span>(<span class="text-teal-400">time</span>() - (<span class="text-pink-400">int</span>)<span class="text-purple-400">$timestamp</span>) > <span class="text-purple-400">$tolerance</span>) {
|
||||
<span class="text-teal-400">http_response_code</span>(<span class="text-amber-400">401</span>);
|
||||
<span class="text-pink-400">die</span>(<span class="text-green-400">'Webhook timestamp expired'</span>);
|
||||
}
|
||||
|
||||
<span class="text-slate-500">// Compute expected signature</span>
|
||||
<span class="text-zinc-500">// Compute expected signature</span>
|
||||
<span class="text-purple-400">$signedPayload</span> = <span class="text-purple-400">$timestamp</span> . <span class="text-green-400">'.'</span> . <span class="text-purple-400">$payload</span>;
|
||||
<span class="text-purple-400">$expectedSignature</span> = <span class="text-teal-400">hash_hmac</span>(<span class="text-green-400">'sha256'</span>, <span class="text-purple-400">$signedPayload</span>, <span class="text-purple-400">$secret</span>);
|
||||
|
||||
<span class="text-slate-500">// Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-zinc-500">// Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-pink-400">if</span> (!<span class="text-teal-400">hash_equals</span>(<span class="text-purple-400">$expectedSignature</span>, <span class="text-purple-400">$signature</span>)) {
|
||||
<span class="text-teal-400">http_response_code</span>(<span class="text-amber-400">401</span>);
|
||||
<span class="text-pink-400">die</span>(<span class="text-green-400">'Invalid webhook signature'</span>);
|
||||
}
|
||||
|
||||
<span class="text-slate-500">// Signature valid - process the webhook</span>
|
||||
<span class="text-zinc-500">// Signature valid - process the webhook</span>
|
||||
<span class="text-purple-400">$event</span> = <span class="text-teal-400">json_decode</span>(<span class="text-purple-400">$payload</span>, <span class="text-pink-400">true</span>);
|
||||
<span class="text-teal-400">processWebhook</span>(<span class="text-purple-400">$event</span>);</code></pre>
|
||||
</div>
|
||||
|
||||
{{-- Node.js Example --}}
|
||||
<h3 class="h4 mb-3 text-slate-800 dark:text-slate-100">Node.js</h3>
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">webhook-handler.js</span>
|
||||
<h3 class="h4 mb-3 text-zinc-800 dark:text-zinc-100">Node.js</h3>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">webhook-handler.js</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-pink-400">const</span> crypto = <span class="text-teal-400">require</span>(<span class="text-green-400">'crypto'</span>);
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-pink-400">const</span> crypto = <span class="text-teal-400">require</span>(<span class="text-green-400">'crypto'</span>);
|
||||
<span class="text-pink-400">const</span> express = <span class="text-teal-400">require</span>(<span class="text-green-400">'express'</span>);
|
||||
|
||||
<span class="text-pink-400">const</span> app = <span class="text-teal-400">express</span>();
|
||||
app.<span class="text-teal-400">use</span>(express.<span class="text-teal-400">raw</span>({ type: <span class="text-green-400">'application/json'</span> }));
|
||||
|
||||
<span class="text-pink-400">const</span> WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;
|
||||
<span class="text-pink-400">const</span> TOLERANCE = <span class="text-amber-400">300</span>; <span class="text-slate-500">// 5 minutes</span>
|
||||
<span class="text-pink-400">const</span> TOLERANCE = <span class="text-amber-400">300</span>; <span class="text-zinc-500">// 5 minutes</span>
|
||||
|
||||
app.<span class="text-teal-400">post</span>(<span class="text-green-400">'/webhook'</span>, (req, res) => {
|
||||
<span class="text-pink-400">const</span> signature = req.headers[<span class="text-green-400">'x-webhook-signature'</span>];
|
||||
<span class="text-pink-400">const</span> timestamp = req.headers[<span class="text-green-400">'x-webhook-timestamp'</span>];
|
||||
<span class="text-pink-400">const</span> payload = req.body;
|
||||
|
||||
<span class="text-slate-500">// Verify timestamp</span>
|
||||
<span class="text-zinc-500">// Verify timestamp</span>
|
||||
<span class="text-pink-400">const</span> now = Math.<span class="text-teal-400">floor</span>(Date.<span class="text-teal-400">now</span>() / <span class="text-amber-400">1000</span>);
|
||||
<span class="text-pink-400">if</span> (Math.<span class="text-teal-400">abs</span>(now - <span class="text-teal-400">parseInt</span>(timestamp)) > TOLERANCE) {
|
||||
<span class="text-pink-400">return</span> res.<span class="text-teal-400">status</span>(<span class="text-amber-400">401</span>).<span class="text-teal-400">send</span>(<span class="text-green-400">'Webhook timestamp expired'</span>);
|
||||
}
|
||||
|
||||
<span class="text-slate-500">// Compute expected signature</span>
|
||||
<span class="text-zinc-500">// Compute expected signature</span>
|
||||
<span class="text-pink-400">const</span> signedPayload = <span class="text-green-400">`${</span>timestamp<span class="text-green-400">}.${</span>payload<span class="text-green-400">}`</span>;
|
||||
<span class="text-pink-400">const</span> expectedSignature = crypto
|
||||
.<span class="text-teal-400">createHmac</span>(<span class="text-green-400">'sha256'</span>, WEBHOOK_SECRET)
|
||||
.<span class="text-teal-400">update</span>(signedPayload)
|
||||
.<span class="text-teal-400">digest</span>(<span class="text-green-400">'hex'</span>);
|
||||
|
||||
<span class="text-slate-500">// Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-zinc-500">// Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-pink-400">if</span> (!crypto.<span class="text-teal-400">timingSafeEqual</span>(
|
||||
Buffer.<span class="text-teal-400">from</span>(expectedSignature),
|
||||
Buffer.<span class="text-teal-400">from</span>(signature)
|
||||
|
|
@ -328,7 +328,7 @@ app.<span class="text-teal-400">post</span>(<span class="text-green-400">'/webho
|
|||
<span class="text-pink-400">return</span> res.<span class="text-teal-400">status</span>(<span class="text-amber-400">401</span>).<span class="text-teal-400">send</span>(<span class="text-green-400">'Invalid webhook signature'</span>);
|
||||
}
|
||||
|
||||
<span class="text-slate-500">// Signature valid - process the webhook</span>
|
||||
<span class="text-zinc-500">// Signature valid - process the webhook</span>
|
||||
<span class="text-pink-400">const</span> event = JSON.<span class="text-teal-400">parse</span>(payload);
|
||||
<span class="text-teal-400">processWebhook</span>(event);
|
||||
res.<span class="text-teal-400">status</span>(<span class="text-amber-400">200</span>).<span class="text-teal-400">send</span>(<span class="text-green-400">'OK'</span>);
|
||||
|
|
@ -336,12 +336,12 @@ app.<span class="text-teal-400">post</span>(<span class="text-green-400">'/webho
|
|||
</div>
|
||||
|
||||
{{-- Python Example --}}
|
||||
<h3 class="h4 mb-3 text-slate-800 dark:text-slate-100">Python</h3>
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">webhook_handler.py</span>
|
||||
<h3 class="h4 mb-3 text-zinc-800 dark:text-zinc-100">Python</h3>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">webhook_handler.py</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-pink-400">import</span> hmac
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-pink-400">import</span> hmac
|
||||
<span class="text-pink-400">import</span> hashlib
|
||||
<span class="text-pink-400">import</span> time
|
||||
<span class="text-pink-400">import</span> os
|
||||
|
|
@ -349,7 +349,7 @@ app.<span class="text-teal-400">post</span>(<span class="text-green-400">'/webho
|
|||
|
||||
app = Flask(__name__)
|
||||
WEBHOOK_SECRET = os.environ[<span class="text-green-400">'WEBHOOK_SECRET'</span>]
|
||||
TOLERANCE = <span class="text-amber-400">300</span> <span class="text-slate-500"># 5 minutes</span>
|
||||
TOLERANCE = <span class="text-amber-400">300</span> <span class="text-zinc-500"># 5 minutes</span>
|
||||
|
||||
<span class="text-pink-400">@</span>app.route(<span class="text-green-400">'/webhook'</span>, methods=[<span class="text-green-400">'POST'</span>])
|
||||
<span class="text-pink-400">def</span> <span class="text-teal-400">webhook</span>():
|
||||
|
|
@ -357,11 +357,11 @@ TOLERANCE = <span class="text-amber-400">300</span> <span class="text-slate-500
|
|||
timestamp = request.headers.get(<span class="text-green-400">'X-Webhook-Timestamp'</span>, <span class="text-green-400">''</span>)
|
||||
payload = request.get_data(as_text=<span class="text-pink-400">True</span>)
|
||||
|
||||
<span class="text-slate-500"># Verify timestamp</span>
|
||||
<span class="text-zinc-500"># Verify timestamp</span>
|
||||
<span class="text-pink-400">if</span> abs(time.time() - int(timestamp)) > TOLERANCE:
|
||||
abort(<span class="text-amber-400">401</span>, <span class="text-green-400">'Webhook timestamp expired'</span>)
|
||||
|
||||
<span class="text-slate-500"># Compute expected signature</span>
|
||||
<span class="text-zinc-500"># Compute expected signature</span>
|
||||
signed_payload = <span class="text-green-400">f'{timestamp}.{payload}'</span>
|
||||
expected_signature = hmac.new(
|
||||
WEBHOOK_SECRET.encode(),
|
||||
|
|
@ -369,40 +369,40 @@ TOLERANCE = <span class="text-amber-400">300</span> <span class="text-slate-500
|
|||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
<span class="text-slate-500"># Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-zinc-500"># Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-pink-400">if not</span> hmac.compare_digest(expected_signature, signature):
|
||||
abort(<span class="text-amber-400">401</span>, <span class="text-green-400">'Invalid webhook signature'</span>)
|
||||
|
||||
<span class="text-slate-500"># Signature valid - process the webhook</span>
|
||||
<span class="text-zinc-500"># Signature valid - process the webhook</span>
|
||||
event = request.get_json()
|
||||
process_webhook(event)
|
||||
<span class="text-pink-400">return</span> <span class="text-green-400">'OK'</span>, <span class="text-amber-400">200</span></code></pre>
|
||||
</div>
|
||||
|
||||
{{-- Ruby Example --}}
|
||||
<h3 class="h4 mb-3 text-slate-800 dark:text-slate-100">Ruby</h3>
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">webhook_handler.rb</span>
|
||||
<h3 class="h4 mb-3 text-zinc-800 dark:text-zinc-100">Ruby</h3>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden mb-6">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">webhook_handler.rb</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-pink-400">require</span> <span class="text-green-400">'sinatra'</span>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-pink-400">require</span> <span class="text-green-400">'sinatra'</span>
|
||||
<span class="text-pink-400">require</span> <span class="text-green-400">'openssl'</span>
|
||||
<span class="text-pink-400">require</span> <span class="text-green-400">'json'</span>
|
||||
|
||||
WEBHOOK_SECRET = ENV[<span class="text-green-400">'WEBHOOK_SECRET'</span>]
|
||||
TOLERANCE = <span class="text-amber-400">300</span> <span class="text-slate-500"># 5 minutes</span>
|
||||
TOLERANCE = <span class="text-amber-400">300</span> <span class="text-zinc-500"># 5 minutes</span>
|
||||
|
||||
post <span class="text-green-400">'/webhook'</span> <span class="text-pink-400">do</span>
|
||||
signature = request.env[<span class="text-green-400">'HTTP_X_WEBHOOK_SIGNATURE'</span>] || <span class="text-green-400">''</span>
|
||||
timestamp = request.env[<span class="text-green-400">'HTTP_X_WEBHOOK_TIMESTAMP'</span>] || <span class="text-green-400">''</span>
|
||||
payload = request.body.read
|
||||
|
||||
<span class="text-slate-500"># Verify timestamp</span>
|
||||
<span class="text-zinc-500"># Verify timestamp</span>
|
||||
<span class="text-pink-400">if</span> (Time.now.to_i - timestamp.to_i).<span class="text-teal-400">abs</span> > TOLERANCE
|
||||
halt <span class="text-amber-400">401</span>, <span class="text-green-400">'Webhook timestamp expired'</span>
|
||||
<span class="text-pink-400">end</span>
|
||||
|
||||
<span class="text-slate-500"># Compute expected signature</span>
|
||||
<span class="text-zinc-500"># Compute expected signature</span>
|
||||
signed_payload = <span class="text-green-400">"#{timestamp}.#{payload}"</span>
|
||||
expected_signature = OpenSSL::HMAC.hexdigest(
|
||||
<span class="text-green-400">'sha256'</span>,
|
||||
|
|
@ -410,12 +410,12 @@ post <span class="text-green-400">'/webhook'</span> <span class="text-pink-400">
|
|||
signed_payload
|
||||
)
|
||||
|
||||
<span class="text-slate-500"># Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-zinc-500"># Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-pink-400">unless</span> Rack::Utils.secure_compare(expected_signature, signature)
|
||||
halt <span class="text-amber-400">401</span>, <span class="text-green-400">'Invalid webhook signature'</span>
|
||||
<span class="text-pink-400">end</span>
|
||||
|
||||
<span class="text-slate-500"># Signature valid - process the webhook</span>
|
||||
<span class="text-zinc-500"># Signature valid - process the webhook</span>
|
||||
event = JSON.parse(payload)
|
||||
process_webhook(event)
|
||||
<span class="text-amber-400">200</span>
|
||||
|
|
@ -423,12 +423,12 @@ post <span class="text-green-400">'/webhook'</span> <span class="text-pink-400">
|
|||
</div>
|
||||
|
||||
{{-- Go Example --}}
|
||||
<h3 class="h4 mb-3 text-slate-800 dark:text-slate-100">Go</h3>
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">webhook_handler.go</span>
|
||||
<h3 class="h4 mb-3 text-zinc-800 dark:text-zinc-100">Go</h3>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">webhook_handler.go</span>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-pink-400">package</span> main
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-pink-400">package</span> main
|
||||
|
||||
<span class="text-pink-400">import</span> (
|
||||
<span class="text-green-400">"crypto/hmac"</span>
|
||||
|
|
@ -443,7 +443,7 @@ post <span class="text-green-400">'/webhook'</span> <span class="text-pink-400">
|
|||
<span class="text-green-400">"time"</span>
|
||||
)
|
||||
|
||||
<span class="text-pink-400">const</span> tolerance = <span class="text-amber-400">300</span> <span class="text-slate-500">// 5 minutes</span>
|
||||
<span class="text-pink-400">const</span> tolerance = <span class="text-amber-400">300</span> <span class="text-zinc-500">// 5 minutes</span>
|
||||
|
||||
<span class="text-pink-400">func</span> <span class="text-teal-400">webhookHandler</span>(w http.ResponseWriter, r *http.Request) {
|
||||
signature := r.Header.Get(<span class="text-green-400">"X-Webhook-Signature"</span>)
|
||||
|
|
@ -452,20 +452,20 @@ post <span class="text-green-400">'/webhook'</span> <span class="text-pink-400">
|
|||
|
||||
payload, _ := io.ReadAll(r.Body)
|
||||
|
||||
<span class="text-slate-500">// Verify timestamp</span>
|
||||
<span class="text-zinc-500">// Verify timestamp</span>
|
||||
ts, _ := strconv.ParseInt(timestamp, <span class="text-amber-400">10</span>, <span class="text-amber-400">64</span>)
|
||||
<span class="text-pink-400">if</span> math.Abs(<span class="text-teal-400">float64</span>(time.Now().Unix()-ts)) > tolerance {
|
||||
http.Error(w, <span class="text-green-400">"Webhook timestamp expired"</span>, <span class="text-amber-400">401</span>)
|
||||
<span class="text-pink-400">return</span>
|
||||
}
|
||||
|
||||
<span class="text-slate-500">// Compute expected signature</span>
|
||||
<span class="text-zinc-500">// Compute expected signature</span>
|
||||
signedPayload := timestamp + <span class="text-green-400">"."</span> + <span class="text-teal-400">string</span>(payload)
|
||||
mac := hmac.New(sha256.New, []<span class="text-teal-400">byte</span>(secret))
|
||||
mac.Write([]<span class="text-teal-400">byte</span>(signedPayload))
|
||||
expectedSignature := hex.EncodeToString(mac.Sum(<span class="text-pink-400">nil</span>))
|
||||
|
||||
<span class="text-slate-500">// Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-zinc-500">// Verify signature (timing-safe comparison)</span>
|
||||
<span class="text-pink-400">if</span> subtle.ConstantTimeCompare(
|
||||
[]<span class="text-teal-400">byte</span>(expectedSignature),
|
||||
[]<span class="text-teal-400">byte</span>(signature),
|
||||
|
|
@ -474,7 +474,7 @@ post <span class="text-green-400">'/webhook'</span> <span class="text-pink-400">
|
|||
<span class="text-pink-400">return</span>
|
||||
}
|
||||
|
||||
<span class="text-slate-500">// Signature valid - process the webhook</span>
|
||||
<span class="text-zinc-500">// Signature valid - process the webhook</span>
|
||||
processWebhook(payload)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}</code></pre>
|
||||
|
|
@ -483,53 +483,53 @@ post <span class="text-green-400">'/webhook'</span> <span class="text-pink-400">
|
|||
|
||||
{{-- Retry Policy --}}
|
||||
<section id="retry-policy" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Retry Policy</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Retry Policy</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
If your endpoint returns a non-2xx status code or times out, we'll retry with exponential backoff:
|
||||
</p>
|
||||
|
||||
<div class="overflow-x-auto mb-4">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-slate-200 dark:border-slate-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Attempt</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-slate-800 dark:text-slate-200">Delay</th>
|
||||
<tr class="border-b border-zinc-200 dark:border-zinc-700">
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Attempt</th>
|
||||
<th class="text-left py-3 px-4 font-medium text-zinc-800 dark:text-zinc-200">Delay</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||
<tbody class="divide-y divide-zinc-200 dark:divide-zinc-700">
|
||||
<tr>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">1 (initial)</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">Immediate</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">1 (initial)</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">Immediate</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">2</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">1 minute</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">2</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">1 minute</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">3</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">5 minutes</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">3</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">5 minutes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">4</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">30 minutes</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">4</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">30 minutes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">5 (final)</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">2 hours</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">5 (final)</td>
|
||||
<td class="py-3 px-4 text-zinc-600 dark:text-zinc-400">2 hours</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p class="text-slate-600 dark:text-slate-400">
|
||||
<p class="text-zinc-600 dark:text-zinc-400">
|
||||
After 5 failed attempts, the delivery is marked as failed. If your endpoint fails 10 consecutive deliveries, it will be automatically disabled. You can re-enable it from your webhook settings.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{{-- Best Practices --}}
|
||||
<section id="best-practices" data-scrollspy-target class="mb-12">
|
||||
<h2 class="h3 mb-4 text-slate-800 dark:text-slate-100">Best Practices</h2>
|
||||
<ul class="space-y-3 text-slate-600 dark:text-slate-400">
|
||||
<h2 class="h3 mb-4 text-zinc-800 dark:text-zinc-100">Best Practices</h2>
|
||||
<ul class="space-y-3 text-zinc-600 dark:text-zinc-400">
|
||||
<li class="flex items-start">
|
||||
<svg class="fill-green-500 shrink-0 mr-3 mt-1" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0zm3.78 5.22a.75.75 0 0 1 0 1.06l-4.5 4.5a.75.75 0 0 1-1.06 0l-2-2a.75.75 0 1 1 1.06-1.06L6.75 9.19l3.97-3.97a.75.75 0 0 1 1.06 0z"/>
|
||||
|
|
@ -570,11 +570,11 @@ post <span class="text-green-400">'/webhook'</span> <span class="text-pink-400">
|
|||
</section>
|
||||
|
||||
{{-- Next steps --}}
|
||||
<div class="flex items-center justify-between pt-8 border-t border-slate-200 dark:border-slate-700">
|
||||
<a href="{{ route('api.guides.qrcodes') }}" class="text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200">
|
||||
<div class="flex items-center justify-between pt-8 border-t border-zinc-200 dark:border-zinc-700">
|
||||
<a href="{{ route('api.guides.qrcodes') }}" class="text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200">
|
||||
← QR Code Generation
|
||||
</a>
|
||||
<a href="{{ route('api.guides.errors') }}" class="text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 font-medium">
|
||||
<a href="{{ route('api.guides.errors') }}" class="text-cyan-600 hover:text-cyan-700 dark:hover:text-cyan-500 font-medium">
|
||||
Error Handling →
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@extends('api::layouts.docs')
|
||||
|
||||
@section('title', 'API Documentation')
|
||||
@section('description', 'Build powerful integrations with the Host UK API. Access biolinks, workspaces, QR codes, and more.')
|
||||
@section('description', 'Build powerful integrations with the API. Access brain memory, content scoring, and more.')
|
||||
|
||||
@section('content')
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 py-12 md:py-20">
|
||||
|
|
@ -9,18 +9,18 @@
|
|||
{{-- Hero --}}
|
||||
<div class="max-w-3xl mx-auto text-center mb-16">
|
||||
<div class="mb-4">
|
||||
<span class="font-nycd text-xl text-blue-600">Developer Documentation</span>
|
||||
<span class="font-nycd text-xl text-cyan-600">Developer Documentation</span>
|
||||
</div>
|
||||
<h1 class="h1 mb-6 text-slate-800 dark:text-slate-100">Build with the Host UK API</h1>
|
||||
<p class="text-xl text-slate-600 dark:text-slate-400 mb-8">
|
||||
Integrate biolinks, workspaces, QR codes, and analytics into your applications.
|
||||
Full REST API with comprehensive documentation and SDK support.
|
||||
<h1 class="h1 mb-6 text-zinc-800 dark:text-zinc-100">Build with the API</h1>
|
||||
<p class="text-xl text-zinc-600 dark:text-zinc-400 mb-8">
|
||||
Store and retrieve agent memories, score content for AI patterns,
|
||||
and integrate intelligent tooling into your applications.
|
||||
</p>
|
||||
<div class="flex flex-wrap justify-center gap-4">
|
||||
<a href="{{ route('api.guides.quickstart') }}" class="btn text-white bg-blue-600 hover:bg-blue-700 px-6 py-3 rounded-sm font-medium">
|
||||
<a href="{{ route('api.guides.quickstart') }}" class="btn text-white bg-cyan-600 hover:bg-cyan-700 px-6 py-3 rounded-sm font-medium">
|
||||
Get Started
|
||||
</a>
|
||||
<a href="{{ route('api.reference') }}" class="btn text-slate-600 bg-white border border-slate-200 hover:border-slate-300 dark:text-slate-300 dark:bg-slate-800 dark:border-slate-700 dark:hover:border-slate-600 px-6 py-3 rounded-sm font-medium">
|
||||
<a href="{{ route('api.reference') }}" class="btn text-zinc-600 bg-white border border-zinc-200 hover:border-zinc-300 dark:text-zinc-300 dark:bg-zinc-800 dark:border-zinc-700 dark:hover:border-zinc-600 px-6 py-3 rounded-sm font-medium">
|
||||
API Reference
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -29,50 +29,44 @@
|
|||
{{-- Features grid --}}
|
||||
<div class="grid md:grid-cols-3 gap-8 mb-16">
|
||||
|
||||
{{-- Authentication --}}
|
||||
<div class="bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm p-6">
|
||||
<div class="w-10 h-10 flex items-center justify-center bg-blue-100 dark:bg-blue-900/30 rounded-sm mb-4">
|
||||
<svg class="w-5 h-5 fill-blue-600" viewBox="0 0 20 20">
|
||||
<path d="M10 2a5 5 0 0 0-5 5v2a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-5a2 2 0 0 0-2-2V7a5 5 0 0 0-5-5zm3 7V7a3 3 0 1 0-6 0v2h6z"/>
|
||||
</svg>
|
||||
{{-- Brain Memory --}}
|
||||
<div class="bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm p-6">
|
||||
<div class="w-10 h-10 flex items-center justify-center bg-cyan-100 dark:bg-cyan-900/30 rounded-sm mb-4">
|
||||
<i class="fa-solid fa-brain text-cyan-600"></i>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-slate-800 dark:text-slate-100">Authentication</h3>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
<h3 class="h4 mb-2 text-zinc-800 dark:text-zinc-100">Brain Memory</h3>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Store and retrieve agent memories with vector search. Powered by Qdrant for semantic retrieval.
|
||||
</p>
|
||||
<a href="{{ route('api.reference') }}#brain" class="text-cyan-600 hover:text-cyan-700 dark:hover:text-cyan-500 text-sm font-medium">
|
||||
Learn more →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- Content Scoring --}}
|
||||
<div class="bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm p-6">
|
||||
<div class="w-10 h-10 flex items-center justify-center bg-purple-100 dark:bg-purple-900/30 rounded-sm mb-4">
|
||||
<i class="fa-solid fa-chart-line text-purple-600"></i>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-zinc-800 dark:text-zinc-100">Content Scoring</h3>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Score text for AI-generated patterns and analyse linguistic imprints via the EaaS scoring engine.
|
||||
</p>
|
||||
<a href="{{ route('api.reference') }}#score" class="text-cyan-600 hover:text-cyan-700 dark:hover:text-cyan-500 text-sm font-medium">
|
||||
Learn more →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- Authentication --}}
|
||||
<div class="bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm p-6">
|
||||
<div class="w-10 h-10 flex items-center justify-center bg-amber-100 dark:bg-amber-900/30 rounded-sm mb-4">
|
||||
<i class="fa-solid fa-key text-amber-600"></i>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-zinc-800 dark:text-zinc-100">Authentication</h3>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Secure API key authentication with scoped permissions. Generate keys from your workspace settings.
|
||||
</p>
|
||||
<a href="{{ route('api.guides.authentication') }}" class="text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 text-sm font-medium">
|
||||
Learn more →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- Biolinks --}}
|
||||
<div class="bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm p-6">
|
||||
<div class="w-10 h-10 flex items-center justify-center bg-purple-100 dark:bg-purple-900/30 rounded-sm mb-4">
|
||||
<svg class="w-5 h-5 fill-purple-600" viewBox="0 0 20 20">
|
||||
<path d="M12.586 4.586a2 2 0 1 1 2.828 2.828l-3 3a2 2 0 0 1-2.828 0 1 1 0 0 0-1.414 1.414 4 4 0 0 0 5.656 0l3-3a4 4 0 0 0-5.656-5.656l-1.5 1.5a1 1 0 1 0 1.414 1.414l1.5-1.5zm-5 5a2 2 0 0 1 2.828 0 1 1 0 1 0 1.414-1.414 4 4 0 0 0-5.656 0l-3 3a4 4 0 1 0 5.656 5.656l1.5-1.5a1 1 0 1 0-1.414-1.414l-1.5 1.5a2 2 0 1 1-2.828-2.828l3-3z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-slate-800 dark:text-slate-100">Biolinks</h3>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
Create, update, and manage biolink pages with blocks, themes, and analytics programmatically.
|
||||
</p>
|
||||
<a href="{{ route('api.guides.biolinks') }}" class="text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 text-sm font-medium">
|
||||
Learn more →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- QR Codes --}}
|
||||
<div class="bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm p-6">
|
||||
<div class="w-10 h-10 flex items-center justify-center bg-teal-100 dark:bg-teal-900/30 rounded-sm mb-4">
|
||||
<svg class="w-5 h-5 fill-teal-600" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M3 4a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4zm2 2V5h1v1H5zm-2 7a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-3zm2 2v-1h1v1H5zm7-13a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1h-3zm1 2v1h1V5h-1z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="h4 mb-2 text-slate-800 dark:text-slate-100">QR Codes</h3>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">
|
||||
Generate customisable QR codes with colours, logos, and multiple formats for any URL.
|
||||
</p>
|
||||
<a href="{{ route('api.guides.qrcodes') }}" class="text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 text-sm font-medium">
|
||||
<a href="{{ route('api.guides.authentication') }}" class="text-cyan-600 hover:text-cyan-700 dark:hover:text-cyan-500 text-sm font-medium">
|
||||
Learn more →
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -81,21 +75,23 @@
|
|||
|
||||
{{-- Quick start code example --}}
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<h2 class="h3 mb-6 text-center text-slate-800 dark:text-slate-100">Quick Start</h2>
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-slate-700">
|
||||
<span class="text-sm text-slate-400">cURL</span>
|
||||
<button class="text-xs text-slate-500 hover:text-slate-300" onclick="navigator.clipboard.writeText(this.closest('.bg-slate-800').querySelector('code').textContent)">
|
||||
<h2 class="h3 mb-6 text-center text-zinc-800 dark:text-zinc-100">Quick Start</h2>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden">
|
||||
<div class="flex items-center justify-between px-4 py-2 border-b border-zinc-700">
|
||||
<span class="text-sm text-zinc-400">cURL</span>
|
||||
<button class="text-xs text-zinc-500 hover:text-zinc-300" onclick="navigator.clipboard.writeText(this.closest('.bg-zinc-800').querySelector('code').textContent)">
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-slate-300"><span class="text-teal-400">curl</span> <span class="text-slate-500">--request</span> GET \
|
||||
<span class="text-slate-500">--url</span> <span class="text-amber-400">'https://api.host.uk.com/api/v1/bio'</span> \
|
||||
<span class="text-slate-500">--header</span> <span class="text-amber-400">'Authorization: Bearer hk_your_api_key'</span></code></pre>
|
||||
<pre class="overflow-x-auto p-4 text-sm"><code class="font-pt-mono text-zinc-300"><span class="text-teal-400">curl</span> <span class="text-zinc-500">--request</span> POST \
|
||||
<span class="text-zinc-500">--url</span> <span class="text-amber-400">'https://api.lthn.ai/v1/brain/recall'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Authorization: Bearer hk_your_api_key'</span> \
|
||||
<span class="text-zinc-500">--header</span> <span class="text-amber-400">'Content-Type: application/json'</span> \
|
||||
<span class="text-zinc-500">--data</span> <span class="text-amber-400">'{"query": "hello world"}'</span></code></pre>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 text-center">
|
||||
<a href="{{ route('api.guides.quickstart') }}" class="text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 text-sm font-medium">
|
||||
<a href="{{ route('api.guides.quickstart') }}" class="text-cyan-600 hover:text-cyan-700 dark:hover:text-cyan-500 text-sm font-medium">
|
||||
View full quick start guide →
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -103,30 +99,30 @@
|
|||
|
||||
{{-- API endpoints preview --}}
|
||||
<div class="mt-16">
|
||||
<h2 class="h3 mb-8 text-center text-slate-800 dark:text-slate-100">API Endpoints</h2>
|
||||
<h2 class="h3 mb-8 text-center text-zinc-800 dark:text-zinc-100">API Endpoints</h2>
|
||||
<div class="grid md:grid-cols-2 gap-4 max-w-4xl mx-auto">
|
||||
@foreach([
|
||||
['method' => 'GET', 'path' => '/api/v1/workspaces', 'desc' => 'List all workspaces'],
|
||||
['method' => 'GET', 'path' => '/api/v1/bio', 'desc' => 'List all biolinks'],
|
||||
['method' => 'POST', 'path' => '/api/v1/bio', 'desc' => 'Create a biolink'],
|
||||
['method' => 'GET', 'path' => '/api/v1/bio/{id}/qr', 'desc' => 'Generate QR code'],
|
||||
['method' => 'GET', 'path' => '/api/v1/shortlinks', 'desc' => 'List short links'],
|
||||
['method' => 'POST', 'path' => '/api/v1/qr/generate', 'desc' => 'Generate QR for any URL'],
|
||||
['method' => 'POST', 'path' => '/v1/brain/remember', 'desc' => 'Store a memory'],
|
||||
['method' => 'POST', 'path' => '/v1/brain/recall', 'desc' => 'Search memories by query'],
|
||||
['method' => 'DELETE', 'path' => '/v1/brain/forget/{id}', 'desc' => 'Delete a memory'],
|
||||
['method' => 'POST', 'path' => '/v1/score/content', 'desc' => 'Score text for AI patterns'],
|
||||
['method' => 'POST', 'path' => '/v1/score/imprint', 'desc' => 'Linguistic imprint analysis'],
|
||||
['method' => 'GET', 'path' => '/v1/score/health', 'desc' => 'Scoring engine health check'],
|
||||
] as $endpoint)
|
||||
<a href="{{ route('api.reference') }}" class="flex items-center gap-4 p-4 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm hover:border-blue-300 dark:hover:border-blue-600 transition-colors">
|
||||
<span class="inline-flex items-center justify-center px-2 py-1 text-xs font-medium rounded {{ $endpoint['method'] === 'GET' ? 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400' : 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400' }}">
|
||||
<a href="{{ route('api.reference') }}" class="flex items-center gap-4 p-4 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm hover:border-cyan-300 dark:hover:border-cyan-600 transition-colors">
|
||||
<span class="inline-flex items-center justify-center px-2 py-1 text-xs font-medium rounded {{ $endpoint['method'] === 'GET' ? 'bg-cyan-100 text-cyan-700 dark:bg-cyan-900/30 dark:text-cyan-400' : ($endpoint['method'] === 'DELETE' ? 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400' : 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400') }}">
|
||||
{{ $endpoint['method'] }}
|
||||
</span>
|
||||
<div class="flex-1 min-w-0">
|
||||
<code class="text-sm font-pt-mono text-slate-800 dark:text-slate-200 truncate block">{{ $endpoint['path'] }}</code>
|
||||
<span class="text-xs text-slate-500 dark:text-slate-400">{{ $endpoint['desc'] }}</span>
|
||||
<code class="text-sm font-pt-mono text-zinc-800 dark:text-zinc-200 truncate block">{{ $endpoint['path'] }}</code>
|
||||
<span class="text-xs text-zinc-500 dark:text-zinc-400">{{ $endpoint['desc'] }}</span>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="mt-8 text-center">
|
||||
<a href="{{ route('api.swagger') }}" class="text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 font-medium">
|
||||
<a href="{{ route('api.swagger') }}" class="text-cyan-600 hover:text-cyan-700 dark:hover:text-cyan-500 font-medium">
|
||||
View all endpoints in Swagger UI →
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,14 @@
|
|||
@php
|
||||
$appName = config('core.app.name', 'Core PHP');
|
||||
@endphp
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="scroll-smooth">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>@yield('title', 'API Documentation') - Host UK</title>
|
||||
<title>@yield('title', 'API Documentation') - {{ $appName }}</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<meta name="description" content="@yield('description', 'Host UK API documentation, guides, and reference.')">
|
||||
|
||||
<!-- Respect user's dark mode preference before page renders -->
|
||||
<script>
|
||||
if (localStorage.getItem('flux.appearance') === 'dark' ||
|
||||
(!localStorage.getItem('flux.appearance') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
</script>
|
||||
<meta name="description" content="@yield('description', $appName . ' REST API documentation, guides, and reference.')">
|
||||
|
||||
<!-- Fonts -->
|
||||
@include('layouts::partials.fonts')
|
||||
|
|
@ -21,22 +16,19 @@
|
|||
<!-- Font Awesome Pro -->
|
||||
<link rel="stylesheet" href="{{ \Core\Helpers\Cdn::versioned('vendor/fontawesome/css/all.min.css') }}">
|
||||
|
||||
<!-- Tailwind / Vite -->
|
||||
<!-- Tailwind / Vite + Flux -->
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
|
||||
<!-- Alpine.js -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<style>[x-cloak] { display: none !important; }</style>
|
||||
@fluxAppearance
|
||||
|
||||
@stack('head')
|
||||
</head>
|
||||
<body class="font-sans antialiased bg-white text-slate-800 dark:bg-slate-900 dark:text-slate-200">
|
||||
<body class="font-sans antialiased bg-white text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200">
|
||||
|
||||
<div class="flex flex-col min-h-screen overflow-hidden">
|
||||
|
||||
{{-- Site header --}}
|
||||
<header class="fixed w-full z-30">
|
||||
<div class="absolute inset-0 bg-white/70 border-b border-slate-200 backdrop-blur-sm -z-10 dark:bg-slate-900/70 dark:border-slate-800" aria-hidden="true"></div>
|
||||
<div class="absolute inset-0 bg-white/70 border-b border-zinc-200 backdrop-blur-sm -z-10 dark:bg-zinc-900/70 dark:border-zinc-800" aria-hidden="true"></div>
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6">
|
||||
<div class="flex items-center justify-between h-16 md:h-20">
|
||||
|
||||
|
|
@ -45,33 +37,33 @@
|
|||
<div class="flex items-center gap-4 md:gap-8">
|
||||
{{-- Logo --}}
|
||||
<a href="{{ route('api.docs') }}" class="flex items-center gap-2">
|
||||
<svg class="w-8 h-8 text-blue-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<svg class="w-8 h-8 text-cyan-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5" />
|
||||
</svg>
|
||||
<span class="font-semibold text-slate-800 dark:text-slate-200">Host UK API</span>
|
||||
<span class="font-semibold text-zinc-800 dark:text-zinc-200">{{ $appName }} API</span>
|
||||
</a>
|
||||
|
||||
{{-- Search --}}
|
||||
<div class="grow" x-data="{ searchOpen: false }">
|
||||
<button
|
||||
class="w-full sm:w-80 text-sm bg-white text-slate-400 inline-flex items-center justify-between leading-5 pl-3 pr-2 py-2 rounded border border-slate-200 hover:border-slate-300 shadow-sm whitespace-nowrap dark:text-slate-500 dark:bg-slate-800 dark:border-slate-700 dark:hover:border-slate-600"
|
||||
class="w-full sm:w-80 text-sm bg-white text-zinc-400 inline-flex items-center justify-between leading-5 pl-3 pr-2 py-2 rounded border border-zinc-200 hover:border-zinc-300 shadow-sm whitespace-nowrap dark:text-zinc-500 dark:bg-zinc-800 dark:border-zinc-700 dark:hover:border-zinc-600"
|
||||
@click.prevent="searchOpen = true"
|
||||
@keydown.slash.window="searchOpen = true"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<i class="fa-solid fa-magnifying-glass w-4 h-4 mr-3 text-slate-400"></i>
|
||||
<i class="fa-solid fa-magnifying-glass w-4 h-4 mr-3 text-zinc-400"></i>
|
||||
<span>Search<span class="hidden sm:inline"> docs</span>...</span>
|
||||
</div>
|
||||
<kbd class="hidden sm:inline-flex items-center justify-center h-5 w-5 text-xs font-medium text-slate-500 rounded border border-slate-200 dark:bg-slate-700 dark:text-slate-400 dark:border-slate-600">/</kbd>
|
||||
<kbd class="hidden sm:inline-flex items-center justify-center h-5 w-5 text-xs font-medium text-zinc-500 rounded border border-zinc-200 dark:bg-zinc-700 dark:text-zinc-400 dark:border-zinc-600">/</kbd>
|
||||
</button>
|
||||
|
||||
{{-- Search modal placeholder --}}
|
||||
<template x-teleport="body">
|
||||
<div x-show="searchOpen" x-cloak>
|
||||
<div class="fixed inset-0 bg-slate-900/20 z-50" @click="searchOpen = false" @keydown.escape.window="searchOpen = false"></div>
|
||||
<div class="fixed inset-0 bg-zinc-900/20 z-50" @click="searchOpen = false" @keydown.escape.window="searchOpen = false"></div>
|
||||
<div class="fixed inset-0 z-50 overflow-hidden flex items-start top-20 justify-center px-4">
|
||||
<div class="bg-white overflow-auto max-w-2xl w-full max-h-[80vh] rounded-lg shadow-lg dark:bg-slate-800 p-4" @click.outside="searchOpen = false">
|
||||
<p class="text-slate-500 dark:text-slate-400 text-center py-8">Search coming soon...</p>
|
||||
<div class="bg-white overflow-auto max-w-2xl w-full max-h-[80vh] rounded-lg shadow-lg dark:bg-zinc-800 p-4" @click.outside="searchOpen = false">
|
||||
<p class="text-zinc-500 dark:text-zinc-400 text-center py-8">Search coming soon...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -82,14 +74,14 @@
|
|||
|
||||
{{-- Desktop nav --}}
|
||||
<nav class="flex items-center gap-6">
|
||||
<a href="{{ route('api.guides') }}" class="text-sm {{ request()->routeIs('api.guides*') ? 'font-medium text-blue-600 dark:text-blue-400' : 'text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200' }}">Guides</a>
|
||||
<a href="{{ route('api.reference') }}" class="text-sm {{ request()->routeIs('api.reference') ? 'font-medium text-blue-600 dark:text-blue-400' : 'text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200' }}">API Reference</a>
|
||||
<a href="{{ route('api.guides') }}" class="text-sm {{ request()->routeIs('api.guides*') ? 'font-medium text-cyan-600 dark:text-cyan-400' : 'text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200' }}">Guides</a>
|
||||
<a href="{{ route('api.reference') }}" class="text-sm {{ request()->routeIs('api.reference') ? 'font-medium text-cyan-600 dark:text-cyan-400' : 'text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200' }}">API Reference</a>
|
||||
|
||||
{{-- API Explorer dropdown --}}
|
||||
<div class="relative" x-data="{ open: false }" @click.outside="open = false">
|
||||
<button
|
||||
@click="open = !open"
|
||||
class="text-sm flex items-center gap-1 {{ request()->routeIs('api.swagger', 'api.scalar', 'api.redoc') ? 'font-medium text-blue-600 dark:text-blue-400' : 'text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200' }}"
|
||||
class="text-sm flex items-center gap-1 {{ request()->routeIs('api.swagger', 'api.scalar', 'api.redoc') ? 'font-medium text-cyan-600 dark:text-cyan-400' : 'text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200' }}"
|
||||
>
|
||||
API Explorer
|
||||
<svg class="w-4 h-4 transition-transform" :class="{ 'rotate-180': open }" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
|
|
@ -104,18 +96,18 @@
|
|||
x-transition:leave="transition ease-in duration-75"
|
||||
x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
class="absolute right-0 mt-2 w-40 origin-top-right rounded-lg bg-white shadow-lg ring-1 ring-slate-200 dark:bg-slate-800 dark:ring-slate-700"
|
||||
class="absolute right-0 mt-2 w-40 origin-top-right rounded-lg bg-white shadow-lg ring-1 ring-zinc-200 dark:bg-zinc-800 dark:ring-zinc-700"
|
||||
x-cloak
|
||||
>
|
||||
<div class="py-1">
|
||||
<a href="{{ route('api.swagger') }}" class="block px-4 py-2 text-sm text-slate-700 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700 {{ request()->routeIs('api.swagger') ? 'bg-slate-100 dark:bg-slate-700' : '' }}">
|
||||
<i class="fa-solid fa-flask w-4 mr-2 text-slate-400"></i>Swagger
|
||||
<a href="{{ route('api.swagger') }}" class="block px-4 py-2 text-sm text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-700 {{ request()->routeIs('api.swagger') ? 'bg-zinc-100 dark:bg-zinc-700' : '' }}">
|
||||
<i class="fa-solid fa-flask w-4 mr-2 text-zinc-400"></i>Swagger
|
||||
</a>
|
||||
<a href="{{ route('api.scalar') }}" class="block px-4 py-2 text-sm text-slate-700 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700 {{ request()->routeIs('api.scalar') ? 'bg-slate-100 dark:bg-slate-700' : '' }}">
|
||||
<i class="fa-solid fa-bolt w-4 mr-2 text-slate-400"></i>Scalar
|
||||
<a href="{{ route('api.scalar') }}" class="block px-4 py-2 text-sm text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-700 {{ request()->routeIs('api.scalar') ? 'bg-zinc-100 dark:bg-zinc-700' : '' }}">
|
||||
<i class="fa-solid fa-bolt w-4 mr-2 text-zinc-400"></i>Scalar
|
||||
</a>
|
||||
<a href="{{ route('api.redoc') }}" class="block px-4 py-2 text-sm text-slate-700 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700 {{ request()->routeIs('api.redoc') ? 'bg-slate-100 dark:bg-slate-700' : '' }}">
|
||||
<i class="fa-solid fa-book w-4 mr-2 text-slate-400"></i>ReDoc
|
||||
<a href="{{ route('api.redoc') }}" class="block px-4 py-2 text-sm text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-700 {{ request()->routeIs('api.redoc') ? 'bg-zinc-100 dark:bg-zinc-700' : '' }}">
|
||||
<i class="fa-solid fa-book w-4 mr-2 text-zinc-400"></i>ReDoc
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -125,7 +117,7 @@
|
|||
<button
|
||||
x-data="{ dark: document.documentElement.classList.contains('dark') }"
|
||||
type="button"
|
||||
class="p-2 text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200"
|
||||
class="p-2 text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200"
|
||||
aria-label="Toggle dark mode"
|
||||
x-on:click="dark = !dark; document.documentElement.classList.toggle('dark'); localStorage.setItem('flux.appearance', dark ? 'dark' : 'light')"
|
||||
>
|
||||
|
|
@ -144,16 +136,15 @@
|
|||
</main>
|
||||
|
||||
{{-- Site footer --}}
|
||||
<footer class="border-t border-slate-200 dark:border-slate-800">
|
||||
<footer class="border-t border-zinc-200 dark:border-zinc-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 py-8">
|
||||
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
||||
<div class="text-sm text-slate-500 dark:text-slate-400">
|
||||
© {{ date('Y') }} Host UK. All rights reserved.
|
||||
<div class="text-sm text-zinc-500 dark:text-zinc-400">
|
||||
© {{ date('Y') }} {{ $appName }}. All rights reserved.
|
||||
</div>
|
||||
<div class="flex gap-6">
|
||||
<a href="https://host.uk.com" class="text-sm text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">Host UK</a>
|
||||
<a href="{{ route('api.openapi.json') }}" class="text-sm text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">OpenAPI Spec</a>
|
||||
<a href="{{ str_replace('api.', 'mcp.', request()->getSchemeAndHttpHost()) }}" class="text-sm text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">MCP Portal</a>
|
||||
<a href="{{ route('api.openapi.json') }}" class="text-sm text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200">OpenAPI Spec</a>
|
||||
<a href="{{ str_replace('api.', 'mcp.', request()->getSchemeAndHttpHost()) }}" class="text-sm text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200">MCP Portal</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -161,6 +152,7 @@
|
|||
|
||||
</div>
|
||||
|
||||
@fluxScripts
|
||||
@stack('scripts')
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
@props(['method', 'path', 'description', 'body' => null, 'response'])
|
||||
|
||||
<div class="mb-8 border border-slate-200 dark:border-slate-700 rounded-sm overflow-hidden">
|
||||
<div class="mb-8 border border-zinc-200 dark:border-zinc-700 rounded-sm overflow-hidden">
|
||||
{{-- Header --}}
|
||||
<div class="flex items-center gap-4 px-4 py-3 bg-slate-50 dark:bg-slate-800/50 border-b border-slate-200 dark:border-slate-700">
|
||||
<div class="flex items-center gap-4 px-4 py-3 bg-zinc-50 dark:bg-zinc-800/50 border-b border-zinc-200 dark:border-zinc-700">
|
||||
<span class="inline-flex items-center justify-center px-2 py-1 text-xs font-semibold rounded
|
||||
@if($method === 'GET') bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400
|
||||
@elseif($method === 'POST') bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400
|
||||
|
|
@ -11,26 +11,26 @@
|
|||
@endif">
|
||||
{{ $method }}
|
||||
</span>
|
||||
<code class="text-sm font-pt-mono text-slate-800 dark:text-slate-200">{{ $path }}</code>
|
||||
<code class="text-sm font-pt-mono text-zinc-800 dark:text-zinc-200">{{ $path }}</code>
|
||||
</div>
|
||||
|
||||
{{-- Body --}}
|
||||
<div class="p-4">
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">{{ $description }}</p>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">{{ $description }}</p>
|
||||
|
||||
@if($body)
|
||||
<div class="mb-4">
|
||||
<h4 class="text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wider mb-2">Request Body</h4>
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-3 text-sm"><code class="font-pt-mono text-slate-300">{{ $body }}</code></pre>
|
||||
<h4 class="text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-2">Request Body</h4>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-3 text-sm"><code class="font-pt-mono text-zinc-300">{{ $body }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div>
|
||||
<h4 class="text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wider mb-2">Response</h4>
|
||||
<div class="bg-slate-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-3 text-sm"><code class="font-pt-mono text-slate-300">{{ $response }}</code></pre>
|
||||
<h4 class="text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-2">Response</h4>
|
||||
<div class="bg-zinc-800 rounded-sm overflow-hidden">
|
||||
<pre class="overflow-x-auto p-3 text-sm"><code class="font-pt-mono text-zinc-300">{{ $response }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>API Reference - Host UK</title>
|
||||
<meta name="description" content="Host UK API Reference - ReDoc documentation">
|
||||
<title>API Reference - {{ config('core.app.name', 'Core PHP') }}</title>
|
||||
<meta name="description" content="{{ config('core.app.name', 'Core PHP') }} API Reference - ReDoc documentation">
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
|
|
|
|||
|
|
@ -6,39 +6,29 @@
|
|||
<div class="flex">
|
||||
|
||||
{{-- Sidebar --}}
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-slate-200 dark:border-slate-800">
|
||||
<aside class="hidden lg:block fixed left-0 top-16 md:top-20 bottom-0 w-64 border-r border-zinc-200 dark:border-zinc-800">
|
||||
<div class="h-full px-4 py-8 overflow-y-auto no-scrollbar">
|
||||
<nav>
|
||||
<h3 class="text-xs font-semibold text-slate-400 uppercase tracking-wider mb-3">Resources</h3>
|
||||
<h3 class="text-xs font-semibold text-zinc-400 uppercase tracking-wider mb-3">Resources</h3>
|
||||
<ul class="space-y-1">
|
||||
<li>
|
||||
<a href="#workspaces" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Workspaces
|
||||
<a href="#brain" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Brain Memory
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#biolinks" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Biolinks
|
||||
<a href="#score" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Content Scoring
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#blocks" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Blocks
|
||||
<a href="#collections" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Collections
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#shortlinks" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Short Links
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#qrcodes" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
QR Codes
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#analytics" data-scrollspy-link class="block px-3 py-2 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Analytics
|
||||
<a href="#health" data-scrollspy-link class="block px-3 py-2 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-sm relative before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-full">
|
||||
Health
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -50,206 +40,104 @@
|
|||
<div class="lg:pl-64 w-full">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 py-12">
|
||||
|
||||
<h1 class="h1 mb-4 text-slate-800 dark:text-slate-100">API Reference</h1>
|
||||
<p class="text-xl text-slate-600 dark:text-slate-400 mb-4">
|
||||
Complete reference for all Host UK API endpoints.
|
||||
<h1 class="h1 mb-4 text-zinc-800 dark:text-zinc-100">API Reference</h1>
|
||||
<p class="text-xl text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Complete reference for all API endpoints.
|
||||
</p>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-12">
|
||||
Base URL: <code class="px-2 py-1 bg-slate-100 dark:bg-slate-800 rounded text-sm font-pt-mono">https://api.host.uk.com/api/v1</code>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-12">
|
||||
Base URL: <code class="px-2 py-1 bg-zinc-100 dark:bg-zinc-800 rounded text-sm font-pt-mono">https://api.lthn.ai/v1</code>
|
||||
</p>
|
||||
|
||||
{{-- Workspaces --}}
|
||||
<section id="workspaces" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-slate-800 dark:text-slate-100 pb-2 border-b border-slate-200 dark:border-slate-700">Workspaces</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-6">
|
||||
Workspaces are containers for your biolinks, short links, and other resources.
|
||||
{{-- Brain Memory --}}
|
||||
<section id="brain" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-zinc-800 dark:text-zinc-100 pb-2 border-b border-zinc-200 dark:border-zinc-700">Brain Memory</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
Store and retrieve agent memories with vector search. Powered by Qdrant for semantic retrieval.
|
||||
</p>
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/workspaces',
|
||||
'description' => 'List all workspaces you have access to.',
|
||||
'response' => '{"data": [{"id": 1, "name": "My Workspace", "slug": "my-workspace"}]}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/workspaces/current',
|
||||
'description' => 'Get the current workspace (from API key context).',
|
||||
'response' => '{"data": {"id": 1, "name": "My Workspace", "slug": "my-workspace"}}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/workspaces/{id}',
|
||||
'description' => 'Get a specific workspace by ID.',
|
||||
'response' => '{"data": {"id": 1, "name": "My Workspace", "slug": "my-workspace"}}'
|
||||
])
|
||||
</section>
|
||||
|
||||
{{-- Biolinks --}}
|
||||
<section id="biolinks" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-slate-800 dark:text-slate-100 pb-2 border-b border-slate-200 dark:border-slate-700">Biolinks</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-6">
|
||||
Biolinks are customisable landing pages with blocks of content.
|
||||
</p>
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/bio',
|
||||
'description' => 'List all biolinks in the workspace.',
|
||||
'response' => '{"data": [{"id": 1, "url": "mypage", "type": "biolink"}]}'
|
||||
'method' => 'POST',
|
||||
'path' => '/brain/remember',
|
||||
'description' => 'Store a new memory in the vector database.',
|
||||
'body' => '{"content": "Go uses structural typing", "type": "fact", "project": "go-agentic", "tags": ["go", "typing"]}',
|
||||
'response' => '{"id": "mem-abc-123", "type": "fact", "project": "go-agentic", "created_at": "2026-03-03T12:00:00+00:00"}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'POST',
|
||||
'path' => '/bio',
|
||||
'description' => 'Create a new biolink.',
|
||||
'body' => '{"url": "mypage", "type": "biolink"}',
|
||||
'response' => '{"data": {"id": 1, "url": "mypage", "type": "biolink"}}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/bio/{id}',
|
||||
'description' => 'Get a specific biolink by ID.',
|
||||
'response' => '{"data": {"id": 1, "url": "mypage", "type": "biolink"}}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'PUT',
|
||||
'path' => '/bio/{id}',
|
||||
'description' => 'Update a biolink.',
|
||||
'body' => '{"url": "newpage"}',
|
||||
'response' => '{"data": {"id": 1, "url": "newpage", "type": "biolink"}}'
|
||||
'path' => '/brain/recall',
|
||||
'description' => 'Search memories by semantic query. Returns ranked results with confidence scores.',
|
||||
'body' => '{"query": "how does typing work in Go", "top_k": 5, "project": "go-agentic"}',
|
||||
'response' => '{"memories": [{"id": "mem-abc-123", "type": "fact", "content": "Go uses structural typing", "confidence": 0.95}], "scores": {"mem-abc-123": 0.87}}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'DELETE',
|
||||
'path' => '/bio/{id}',
|
||||
'description' => 'Delete a biolink.',
|
||||
'response' => '{"message": "Deleted successfully"}'
|
||||
'path' => '/brain/forget/{id}',
|
||||
'description' => 'Delete a specific memory by ID.',
|
||||
'response' => '{"deleted": true}'
|
||||
])
|
||||
</section>
|
||||
|
||||
{{-- Blocks --}}
|
||||
<section id="blocks" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-slate-800 dark:text-slate-100 pb-2 border-b border-slate-200 dark:border-slate-700">Blocks</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-6">
|
||||
Blocks are content elements within a biolink page.
|
||||
{{-- Content Scoring --}}
|
||||
<section id="score" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-zinc-800 dark:text-zinc-100 pb-2 border-b border-zinc-200 dark:border-zinc-700">Content Scoring</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
Score text for AI patterns and analyse linguistic imprints via the EaaS scoring engine.
|
||||
</p>
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/bio/{bioId}/blocks',
|
||||
'description' => 'List all blocks for a biolink.',
|
||||
'response' => '{"data": [{"id": 1, "type": "link", "data": {"title": "My Link"}}]}'
|
||||
'method' => 'POST',
|
||||
'path' => '/score/content',
|
||||
'description' => 'Score text for AI-generated content patterns. Returns a score (0-1), confidence, and label.',
|
||||
'body' => '{"text": "The text to analyse for AI patterns", "prompt": "Optional scoring prompt"}',
|
||||
'response' => '{"score": 0.23, "confidence": 0.91, "label": "human"}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'POST',
|
||||
'path' => '/bio/{bioId}/blocks',
|
||||
'description' => 'Add a new block to a biolink.',
|
||||
'body' => '{"type": "link", "data": {"title": "My Link", "url": "https://example.com"}}',
|
||||
'response' => '{"data": {"id": 1, "type": "link", "data": {"title": "My Link"}}}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'PUT',
|
||||
'path' => '/bio/{bioId}/blocks/{id}',
|
||||
'description' => 'Update a block.',
|
||||
'body' => '{"data": {"title": "Updated Link"}}',
|
||||
'response' => '{"data": {"id": 1, "type": "link", "data": {"title": "Updated Link"}}}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'DELETE',
|
||||
'path' => '/bio/{bioId}/blocks/{id}',
|
||||
'description' => 'Delete a block.',
|
||||
'response' => '{"message": "Deleted successfully"}'
|
||||
'path' => '/score/imprint',
|
||||
'description' => 'Perform linguistic imprint analysis on text. Returns a unique imprint fingerprint.',
|
||||
'body' => '{"text": "The text to analyse for linguistic patterns"}',
|
||||
'response' => '{"imprint": "abc123def456", "confidence": 0.88}'
|
||||
])
|
||||
</section>
|
||||
|
||||
{{-- Short Links --}}
|
||||
<section id="shortlinks" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-slate-800 dark:text-slate-100 pb-2 border-b border-slate-200 dark:border-slate-700">Short Links</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-6">
|
||||
Short links redirect to any URL with tracking.
|
||||
{{-- Collections --}}
|
||||
<section id="collections" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-zinc-800 dark:text-zinc-100 pb-2 border-b border-zinc-200 dark:border-zinc-700">Collections</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
Manage vector database collections for brain memory storage.
|
||||
</p>
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/shortlinks',
|
||||
'description' => 'List all short links in the workspace.',
|
||||
'response' => '{"data": [{"id": 1, "url": "abc123", "destination": "https://example.com"}]}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'POST',
|
||||
'path' => '/shortlinks',
|
||||
'description' => 'Create a new short link.',
|
||||
'body' => '{"destination": "https://example.com"}',
|
||||
'response' => '{"data": {"id": 1, "url": "abc123", "destination": "https://example.com"}}'
|
||||
'path' => '/brain/collections',
|
||||
'description' => 'Ensure the workspace collection exists in the vector database. Creates it if missing.',
|
||||
'response' => '{"status": "ok"}'
|
||||
])
|
||||
</section>
|
||||
|
||||
{{-- QR Codes --}}
|
||||
<section id="qrcodes" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-slate-800 dark:text-slate-100 pb-2 border-b border-slate-200 dark:border-slate-700">QR Codes</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-6">
|
||||
Generate customisable QR codes for biolinks or any URL.
|
||||
{{-- Health --}}
|
||||
<section id="health" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-zinc-800 dark:text-zinc-100 pb-2 border-b border-zinc-200 dark:border-zinc-700">Health</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
Health check endpoints. These do not require authentication.
|
||||
</p>
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/bio/{id}/qr',
|
||||
'description' => 'Get QR code data for a biolink.',
|
||||
'response' => '{"data": {"svg": "<svg>...</svg>", "url": "https://lt.hn/mypage"}}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/bio/{id}/qr/download',
|
||||
'description' => 'Download QR code as PNG/SVG. Query params: format (png|svg), size (100-2000).',
|
||||
'response' => 'Binary image data'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'POST',
|
||||
'path' => '/qr/generate',
|
||||
'description' => 'Generate QR code for any URL.',
|
||||
'body' => '{"url": "https://example.com", "format": "svg", "size": 300}',
|
||||
'response' => '{"data": {"svg": "<svg>...</svg>"}}'
|
||||
])
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/qr/options',
|
||||
'description' => 'Get available QR code customisation options.',
|
||||
'response' => '{"data": {"formats": ["png", "svg"], "sizes": {"min": 100, "max": 2000}}}'
|
||||
])
|
||||
</section>
|
||||
|
||||
{{-- Analytics --}}
|
||||
<section id="analytics" data-scrollspy-target class="mb-16">
|
||||
<h2 class="h2 mb-6 text-slate-800 dark:text-slate-100 pb-2 border-b border-slate-200 dark:border-slate-700">Analytics</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-6">
|
||||
View analytics data for your biolinks.
|
||||
</p>
|
||||
|
||||
@include('api::partials.endpoint', [
|
||||
'method' => 'GET',
|
||||
'path' => '/bio/{id}/analytics',
|
||||
'description' => 'Get analytics for a biolink. Query params: period (7d|30d|90d).',
|
||||
'response' => '{"data": {"views": 1234, "clicks": 567, "unique_visitors": 890}}'
|
||||
'path' => '/score/health',
|
||||
'description' => 'Check the health of the scoring engine and its upstream services.',
|
||||
'response' => '{"status": "healthy", "upstream_status": 200}'
|
||||
])
|
||||
</section>
|
||||
|
||||
{{-- CTA --}}
|
||||
<div class="mt-12 p-6 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-sm text-center">
|
||||
<h3 class="h4 mb-2 text-slate-800 dark:text-slate-100">Try it out</h3>
|
||||
<p class="text-slate-600 dark:text-slate-400 mb-4">Test endpoints interactively with Swagger UI.</p>
|
||||
<a href="{{ route('api.swagger') }}" class="btn text-white bg-blue-600 hover:bg-blue-700 px-6 py-2 rounded-sm font-medium">
|
||||
<div class="mt-12 p-6 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-sm text-center">
|
||||
<h3 class="h4 mb-2 text-zinc-800 dark:text-zinc-100">Try it out</h3>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">Test endpoints interactively with Swagger UI.</p>
|
||||
<a href="{{ route('api.swagger') }}" class="btn text-white bg-cyan-600 hover:bg-cyan-700 px-6 py-2 rounded-sm font-medium">
|
||||
Open Swagger UI
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>API Reference - Host UK</title>
|
||||
<meta name="description" content="Host UK API Reference - Interactive documentation with code samples">
|
||||
<title>API Reference - {{ config('core.app.name', 'Core PHP') }}</title>
|
||||
<meta name="description" content="{{ config('core.app.name', 'Core PHP') }} API Reference - Interactive documentation with code samples">
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
|
|
@ -60,8 +60,8 @@
|
|||
"clientKey": "guzzle"
|
||||
},
|
||||
"metaData": {
|
||||
"title": "Host UK API",
|
||||
"description": "API documentation for Host UK services"
|
||||
"title": "{{ config('core.app.name', 'Core PHP') }} API",
|
||||
"description": "API documentation for {{ config('core.app.name', 'Core PHP') }}"
|
||||
}
|
||||
}'
|
||||
></script>
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@
|
|||
@section('content')
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 py-8">
|
||||
<div class="mb-8">
|
||||
<h1 class="h2 mb-2 text-slate-800 dark:text-slate-100">Swagger UI</h1>
|
||||
<p class="text-slate-600 dark:text-slate-400">
|
||||
<h1 class="h2 mb-2 text-zinc-800 dark:text-zinc-100">Swagger UI</h1>
|
||||
<p class="text-zinc-600 dark:text-zinc-400">
|
||||
Interactive API explorer. Try out endpoints directly from your browser.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="swagger-ui" class="bg-white dark:bg-slate-800 rounded-sm border border-slate-200 dark:border-slate-700 p-4"></div>
|
||||
<div id="swagger-ui" class="bg-white dark:bg-zinc-800 rounded-sm border border-zinc-200 dark:border-zinc-700 p-4"></div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
|
|
|
|||
Reference in a new issue