php-api/changelog/2026/jan/API_DOCUMENTATION_PLAN.md
Snider 058d65252d docs: add API documentation plan and module code review
Add comprehensive API documentation strategy for api.host.uk.com including
OpenAPI/Scramble setup, SDK generation configs for 11 languages, and
multi-registry publishing workflow.

Include updated code review documenting Wave 2 improvements bringing the
Api module to 92/100 production readiness with all P1 issues resolved.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 16:21:41 +00:00

35 KiB

API Documentation Plan

Goal: Expose Host Hub APIs via api.host.uk.com with OpenAPI documentation, enabling SDK generation for multiple languages.


Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                         api.host.uk.com                             │
│                                                                     │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────────┐  │
│  │   Swagger    │  │    ReDoc     │  │     SDK Downloads        │  │
│  │   UI /docs   │  │  /reference  │  │  /sdks/php, /sdks/js...  │  │
│  └──────────────┘  └──────────────┘  └──────────────────────────┘  │
│                              │                                      │
│                              ▼                                      │
│                    ┌──────────────────┐                            │
│                    │   openapi.json   │                            │
│                    │   openapi.yaml   │                            │
│                    └────────┬─────────┘                            │
│                              │                                      │
└──────────────────────────────┼──────────────────────────────────────┘
                               │
                               ▼
┌──────────────────────────────────────────────────────────────────────┐
│                         Host Hub Laravel                             │
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │                      API Routes                              │    │
│  │  /api/v1/workspaces, /api/v1/entitlements, /api/v1/commerce │    │
│  └─────────────────────────────────────────────────────────────┘    │
│                              │                                       │
│              ┌───────────────┼───────────────┐                      │
│              ▼               ▼               ▼                      │
│      ┌────────────┐  ┌────────────┐  ┌────────────┐                │
│      │ Scramble   │  │ Controller │  │ Form       │                │
│      │ (auto-gen) │  │ Attributes │  │ Requests   │                │
│      └────────────┘  └────────────┘  └────────────┘                │
│                                                                      │
│  Note: MCP tools may call these same endpoints internally.          │
│  For agent-native interface, see mcp.host.uk.com                    │
└──────────────────────────────────────────────────────────────────────┘

Package Selection: Scramble

Why Scramble over L5-Swagger:

  • Zero annotations required - generates from code
  • Understands Laravel conventions (Form Requests, Resources, Policies)
  • Active development, Laravel-native
  • Supports PHP 8 attributes for customization when needed
composer require dedoc/scramble

API Structure

Version Strategy

/api/v1/*  - Current stable
/api/v2/*  - Future (when breaking changes needed)

Version in URL, not headers. Simple, cacheable, debuggable.

Authentication

┌─────────────────────────────────────────────────────────────┐
│  Authentication Methods                                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. API Keys (Primary for SDK usage)                        │
│     Authorization: Bearer <api_key>                         │
│     - Scoped to workspace                                   │
│     - Rotatable, revocable                                  │
│     - Rate limited per key                                  │
│                                                             │
│  2. OAuth 2.0 (For third-party apps)                        │
│     - Authorization code flow                               │
│     - Scopes map to entitlements                            │
│     - Managed via Passport                                  │
│                                                             │
│  3. Session (Internal dashboard calls)                      │
│     - Sanctum SPA authentication                            │
│     - CSRF protected                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Endpoint Categories

/api/v1:
  /auth:
    - POST /token           # Exchange credentials for token
    - DELETE /token         # Revoke token
    - GET /me               # Current user info

  /workspaces:
    - GET /                 # List user's workspaces
    - GET /{id}             # Get workspace details
    - POST /                # Create workspace
    - PATCH /{id}           # Update workspace
    - DELETE /{id}          # Delete workspace

  /workspaces/{workspace}:
    /members:
      - GET /               # List members
      - POST /              # Invite member
      - DELETE /{user}      # Remove member

    /entitlements:
      - GET /               # Get entitlement summary
      - GET /check/{feature} # Check specific feature
      - GET /usage          # Usage breakdown

    /biolinks:
      - GET /               # List biolinks
      - POST /              # Create biolink
      - GET /{id}           # Get biolink
      - PATCH /{id}         # Update biolink
      - DELETE /{id}        # Delete biolink

    /links:
      - GET /               # List short links
      - POST /              # Create short link
      - GET /{id}           # Get link details
      - PATCH /{id}         # Update link
      - DELETE /{id}        # Delete link
      - GET /{id}/stats     # Link analytics

    /qr-codes:
      - GET /               # List QR codes
      - POST /              # Create QR code
      - GET /{id}           # Get QR code
      - GET /{id}/download  # Download QR image

  /commerce:
    /subscriptions:
      - GET /               # Current subscription
      - POST /change        # Change plan (preview)
      - POST /change/confirm # Execute plan change
      - POST /cancel        # Cancel subscription

    /invoices:
      - GET /               # List invoices
      - GET /{id}           # Get invoice
      - GET /{id}/pdf       # Download PDF

    /payment-methods:
      - GET /               # List payment methods
      - POST /              # Add payment method
      - DELETE /{id}        # Remove payment method
      - POST /{id}/default  # Set as default

  /support:
    /tickets:
      - GET /               # List tickets
      - POST /              # Create ticket
      - GET /{id}           # Get ticket
      - POST /{id}/reply    # Reply to ticket

  /webhooks:
    - GET /                 # List webhook endpoints
    - POST /                # Create webhook endpoint
    - PATCH /{id}           # Update webhook
    - DELETE /{id}          # Delete webhook
    - GET /{id}/deliveries  # View delivery history

Implementation

Phase 1: Core Setup

// config/scramble.php
return [
    'info' => [
        'title' => 'Host Hub API',
        'description' => 'API for managing workspaces, biolinks, short links, and commerce.',
        'version' => '1.0.0',
        'contact' => [
            'name' => 'Host UK Support',
            'url' => 'https://support.host.uk.com',
            'email' => 'api@host.uk.com',
        ],
    ],

    'servers' => [
        ['url' => 'https://api.host.uk.com', 'description' => 'Production'],
        ['url' => 'https://api.staging.host.uk.com', 'description' => 'Staging'],
    ],

    'api_path' => 'api/v1',
    'api_domain' => null,

    // Generate docs at this path
    'export_path' => 'api/openapi.json',
];

Phase 2: API Key System

// database/migrations/create_api_keys_table.php
Schema::create('api_keys', function (Blueprint $table) {
    $table->id();
    $table->foreignId('workspace_id')->constrained()->cascadeOnDelete();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->string('name');
    $table->string('key', 64)->unique(); // hashed
    $table->string('prefix', 8);         // visible prefix for identification
    $table->json('scopes')->nullable();  // ['read', 'write', 'delete']
    $table->timestamp('last_used_at')->nullable();
    $table->timestamp('expires_at')->nullable();
    $table->timestamps();
    $table->softDeletes();

    $table->index(['workspace_id', 'deleted_at']);
});

// app/Models/ApiKey.php
class ApiKey extends Model
{
    use SoftDeletes;

    protected $casts = [
        'scopes' => 'array',
        'last_used_at' => 'datetime',
        'expires_at' => 'datetime',
    ];

    public static function generate(Workspace $workspace, User $user, string $name): array
    {
        $plainKey = Str::random(48);
        $prefix = Str::random(8);

        $apiKey = static::create([
            'workspace_id' => $workspace->id,
            'user_id' => $user->id,
            'name' => $name,
            'key' => hash('sha256', $plainKey),
            'prefix' => $prefix,
            'scopes' => ['read', 'write'],
        ]);

        // Return plain key only once - never stored
        return [
            'api_key' => $apiKey,
            'plain_key' => "{$prefix}_{$plainKey}", // hk_xxxxxxxx_xxxxx...
        ];
    }

    public static function findByPlainKey(string $plainKey): ?static
    {
        [$prefix, $key] = explode('_', $plainKey, 2);

        return static::where('prefix', $prefix)
            ->where('key', hash('sha256', $key))
            ->whereNull('deleted_at')
            ->where(fn($q) => $q->whereNull('expires_at')->orWhere('expires_at', '>', now()))
            ->first();
    }

    public function recordUsage(): void
    {
        $this->update(['last_used_at' => now()]);
    }
}

Phase 3: Authentication Guard

// app/Http/Middleware/AuthenticateApiKey.php
class AuthenticateApiKey
{
    public function handle(Request $request, Closure $next)
    {
        $token = $request->bearerToken();

        if (!$token) {
            return response()->json([
                'error' => 'unauthorized',
                'message' => 'API key required',
            ], 401);
        }

        // Check if it's an API key (prefixed with hk_)
        if (str_starts_with($token, 'hk_')) {
            $apiKey = ApiKey::findByPlainKey($token);

            if (!$apiKey) {
                return response()->json([
                    'error' => 'unauthorized',
                    'message' => 'Invalid API key',
                ], 401);
            }

            $apiKey->recordUsage();

            // Set workspace context
            $request->setUserResolver(fn() => $apiKey->user);
            $request->attributes->set('api_key', $apiKey);
            $request->attributes->set('workspace', $apiKey->workspace);

            return $next($request);
        }

        // Fall back to Sanctum for OAuth tokens
        return app(Authenticate::class)->handle($request, $next, 'sanctum');
    }
}

Phase 4: API Controllers

// app/Http/Controllers/Api/V1/WorkspaceController.php
namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Http\Resources\WorkspaceResource;
use App\Http\Requests\Api\CreateWorkspaceRequest;
use App\Http\Requests\Api\UpdateWorkspaceRequest;

/**
 * @tags Workspaces
 */
class WorkspaceController extends Controller
{
    /**
     * List workspaces
     *
     * Returns all workspaces the authenticated user has access to.
     *
     * @response WorkspaceResource[]
     */
    public function index(Request $request)
    {
        $workspaces = $request->user()
            ->workspaces()
            ->with('subscription.package')
            ->paginate();

        return WorkspaceResource::collection($workspaces);
    }

    /**
     * Get workspace
     *
     * @response WorkspaceResource
     */
    public function show(Workspace $workspace)
    {
        $this->authorize('view', $workspace);

        return new WorkspaceResource(
            $workspace->load('subscription.package', 'members')
        );
    }

    /**
     * Create workspace
     *
     * @response 201 WorkspaceResource
     */
    public function store(CreateWorkspaceRequest $request)
    {
        $workspace = Workspace::create([
            'name' => $request->name,
            'slug' => $request->slug ?? Str::slug($request->name),
            'owner_id' => $request->user()->id,
        ]);

        return new WorkspaceResource($workspace);
    }
}

Phase 5: API Resources (Response Schemas)

// app/Http/Resources/WorkspaceResource.php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

/**
 * @property int $id
 * @property string $name
 * @property string $slug
 * @property string $created_at
 */
class WorkspaceResource extends JsonResource
{
    public function toArray($request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'slug' => $this->slug,
            'created_at' => $this->created_at->toIso8601String(),
            'updated_at' => $this->updated_at->toIso8601String(),

            // Relationships
            'subscription' => new SubscriptionResource($this->whenLoaded('subscription')),
            'members' => UserResource::collection($this->whenLoaded('members')),
            'member_count' => $this->whenCounted('members'),

            // Computed
            'links' => [
                'self' => route('api.v1.workspaces.show', $this->id),
                'biolinks' => route('api.v1.workspaces.biolinks.index', $this->id),
                'entitlements' => route('api.v1.workspaces.entitlements.index', $this->id),
            ],
        ];
    }
}

SDK Generation

Target Registries (Maximum Developer Signal)

┌─────────────────────────────────────────────────────────────────────────────┐
│                          SDK Distribution Matrix                            │
├──────────────┬────────────────────┬─────────────────────┬───────────────────┤
│ Language     │ Registry           │ Audience            │ Generator         │
├──────────────┼────────────────────┼─────────────────────┼───────────────────┤
│ PHP          │ Packagist          │ Web devs            │ php               │
│ TypeScript   │ npm                │ Frontend/Node       │ typescript-fetch  │
│ Python       │ PyPI               │ Scripts/Data/AI     │ python            │
│ Go           │ pkg.go.dev         │ DevOps/Cloud/CLI    │ go                │
│ Rust         │ crates.io          │ Systems/Performance │ rust              │
│ Ruby         │ RubyGems           │ Rails/Web           │ ruby              │
│ Java         │ Maven Central      │ Enterprise          │ java              │
│ C#/.NET      │ NuGet              │ Enterprise/Windows  │ csharp-netcore    │
│ Kotlin       │ Maven Central      │ Android/Modern Java │ kotlin            │
│ Swift        │ Swift PM           │ Apple ecosystem     │ swift5            │
│ Dart         │ pub.dev            │ Flutter/Mobile      │ dart              │
├──────────────┴────────────────────┴─────────────────────┴───────────────────┤
│                        Infrastructure / DevOps                              │
├──────────────┬────────────────────┬─────────────────────┬───────────────────┤
│ Ansible      │ Ansible Galaxy     │ SysAdmins           │ SwaggerToAnsible  │
│ Terraform    │ Terraform Registry │ IaC DevOps          │ Custom provider   │
│ Pulumi       │ Pulumi Registry    │ Modern IaC          │ Pulumi bridge     │
│ CLI (Go)     │ Homebrew/apt/yum   │ Terminal users      │ go + goreleaser   │
│ GitHub Action│ GH Marketplace     │ CI/CD users         │ Custom            │
└──────────────┴────────────────────┴─────────────────────┴───────────────────┘

Priority Tiers

Tier 1 - Core (Day 1):

  • PHP, TypeScript, Python (your primary audiences)

Tier 2 - High Signal (Week 1):

  • Go (DevOps love, plus builds CLI binary)
  • Rust (growing fast, crates.io visibility)
  • Ruby (still strong web community)

Tier 3 - Enterprise (Week 2):

  • Java, Kotlin (Maven Central = enterprise discovery)
  • C#/.NET (NuGet = Microsoft ecosystem)

Tier 4 - Mobile/Niche:

  • Swift (Apple developers)
  • Dart (Flutter mobile)

Tier 5 - Infrastructure:

  • Ansible (you have SwaggerToAnsible)
  • Terraform Provider (huge IaC market)
  • CLI binary via Homebrew
  • GitHub Action

OpenAPI Generator Configs

# sdk-config/php.yaml
generatorName: php
outputDir: ./sdks/php
additionalProperties:
  packageName: HostHubSdk
  invokerPackage: HostUK\HostHub
  apiPackage: Api
  modelPackage: Model
  composerVendorName: host-uk
  composerProjectName: hosthub-sdk
  gitUserId: host-uk
  gitRepoId: hosthub-php-sdk

# sdk-config/typescript.yaml
generatorName: typescript-fetch
outputDir: ./sdks/typescript
additionalProperties:
  npmName: "@host-uk/hosthub-sdk"
  npmVersion: "1.0.0"
  supportsES6: true
  typescriptThreePlus: true

# sdk-config/python.yaml
generatorName: python
outputDir: ./sdks/python
additionalProperties:
  packageName: hosthub
  projectName: hosthub-sdk
  packageVersion: "1.0.0"

# sdk-config/go.yaml
generatorName: go
outputDir: ./sdks/go
additionalProperties:
  packageName: hosthub
  moduleName: github.com/host-uk/hosthub-go

# sdk-config/rust.yaml
generatorName: rust
outputDir: ./sdks/rust
additionalProperties:
  packageName: hosthub
  packageVersion: "1.0.0"

# sdk-config/ruby.yaml
generatorName: ruby
outputDir: ./sdks/ruby
additionalProperties:
  gemName: hosthub
  gemVersion: "1.0.0"
  gemAuthor: "Host UK"
  gemHomepage: "https://api.host.uk.com"

# sdk-config/java.yaml
generatorName: java
outputDir: ./sdks/java
additionalProperties:
  groupId: com.hostuk
  artifactId: hosthub-sdk
  artifactVersion: "1.0.0"
  invokerPackage: com.hostuk.hosthub
  apiPackage: com.hostuk.hosthub.api
  modelPackage: com.hostuk.hosthub.model

# sdk-config/csharp.yaml
generatorName: csharp-netcore
outputDir: ./sdks/csharp
additionalProperties:
  packageName: HostUK.HostHub
  packageVersion: "1.0.0"
  targetFramework: "net6.0"

# sdk-config/kotlin.yaml
generatorName: kotlin
outputDir: ./sdks/kotlin
additionalProperties:
  groupId: com.hostuk
  artifactId: hosthub-sdk
  packageName: com.hostuk.hosthub

# sdk-config/swift.yaml
generatorName: swift5
outputDir: ./sdks/swift
additionalProperties:
  projectName: HostHubSDK
  podVersion: "1.0.0"

# sdk-config/dart.yaml
generatorName: dart
outputDir: ./sdks/dart
additionalProperties:
  pubName: hosthub
  pubVersion: "1.0.0"
  pubAuthor: "Host UK"

CLI Tool (Go-based)

// cmd/hosthub/main.go
// Built from Go SDK, distributed via:
// - Homebrew (macOS/Linux)
// - apt repository (Debian/Ubuntu)
// - yum repository (RHEL/CentOS)
// - Scoop (Windows)
// - Direct binary downloads

// Example usage:
// $ hosthub workspaces list
// $ hosthub links create --url https://example.com
// $ hosthub biolinks get bl_123
# .goreleaser.yml
builds:
  - main: ./cmd/hosthub
    binary: hosthub
    goos: [linux, darwin, windows]
    goarch: [amd64, arm64]

brews:
  - tap:
      owner: host-uk
      name: homebrew-tap
    name: hosthub
    homepage: https://api.host.uk.com

nfpms:
  - package_name: hosthub
    vendor: Host UK
    formats: [deb, rpm]

Terraform Provider

terraform-provider-hosthub/
├── internal/
│   └── provider/
│       ├── provider.go
│       ├── workspace_resource.go
│       ├── biolink_resource.go
│       └── link_resource.go
└── examples/
    └── main.tf
# Example Terraform usage
terraform {
  required_providers {
    hosthub = {
      source  = "host-uk/hosthub"
      version = "~> 1.0"
    }
  }
}

provider "hosthub" {
  api_key = var.hosthub_api_key
}

resource "hosthub_workspace" "main" {
  name = "My Workspace"
  slug = "my-workspace"
}

resource "hosthub_biolink" "landing" {
  workspace_id = hosthub_workspace.main.id
  name         = "Landing Page"
  url          = "landing"
}

GitHub Action

# action.yml
name: 'Host Hub Action'
description: 'Manage Host Hub resources in CI/CD'
branding:
  icon: 'link'
  color: 'blue'

inputs:
  api-key:
    description: 'Host Hub API key'
    required: true
  command:
    description: 'Command to run (e.g., "links create")'
    required: true

runs:
  using: 'node16'
  main: 'dist/index.js'
# Usage in workflow
- uses: host-uk/hosthub-action@v1
  with:
    api-key: ${{ secrets.HOSTHUB_API_KEY }}
    command: links create --url ${{ github.event.deployment.url }}

Package Registry Summary

Registry Package Name Install Command
Packagist host-uk/hosthub-sdk composer require host-uk/hosthub-sdk
npm @host-uk/hosthub-sdk npm install @host-uk/hosthub-sdk
PyPI hosthub pip install hosthub
pkg.go.dev github.com/host-uk/hosthub-go go get github.com/host-uk/hosthub-go
crates.io hosthub cargo add hosthub
RubyGems hosthub gem install hosthub
Maven com.hostuk:hosthub-sdk Maven/Gradle dependency
NuGet HostUK.HostHub dotnet add package HostUK.HostHub
pub.dev hosthub dart pub add hosthub
Swift PM HostHubSDK Package.swift dependency
Ansible Galaxy hostuk.hosthub ansible-galaxy collection install hostuk.hosthub
Terraform host-uk/hosthub required_providers block
Homebrew hosthub brew install host-uk/tap/hosthub
GitHub Actions host-uk/hosthub-action uses: host-uk/hosthub-action@v1

Generation Script

#!/bin/bash
# scripts/generate-sdks.sh

OPENAPI_FILE="storage/app/openapi.json"
OUTPUT_DIR="./sdks"

# Export fresh OpenAPI spec
php artisan scramble:export

# Array of all SDK configs
SDKS=(
  "php"
  "typescript"
  "python"
  "go"
  "rust"
  "ruby"
  "java"
  "csharp"
  "kotlin"
  "swift"
  "dart"
)

# Generate all SDKs
for sdk in "${SDKS[@]}"; do
  echo "Generating $sdk SDK..."
  openapi-generator-cli generate \
    -i $OPENAPI_FILE \
    -c sdk-config/$sdk.yaml \
    -o $OUTPUT_DIR/$sdk
done

echo "All SDKs generated in $OUTPUT_DIR"

Publish Script

#!/bin/bash
# scripts/publish-sdks.sh

VERSION=$1

if [ -z "$VERSION" ]; then
  echo "Usage: ./publish-sdks.sh <version>"
  exit 1
fi

# PHP → Packagist (auto via GitHub webhook)
echo "PHP: Push to host-uk/hosthub-php-sdk triggers Packagist"

# TypeScript → npm
cd sdks/typescript
npm version $VERSION
npm publish --access public
cd ../..

# Python → PyPI
cd sdks/python
python -m build
twine upload dist/*
cd ../..

# Go → pkg.go.dev (auto on push + tag)
cd sdks/go
git tag v$VERSION
git push origin v$VERSION
cd ../..

# Rust → crates.io
cd sdks/rust
cargo publish
cd ../..

# Ruby → RubyGems
cd sdks/ruby
gem build hosthub.gemspec
gem push hosthub-$VERSION.gem
cd ../..

# Java/Kotlin → Maven Central
cd sdks/java
./gradlew publish
cd ../..

# C# → NuGet
cd sdks/csharp
dotnet pack -c Release
dotnet nuget push **/*.nupkg --source https://api.nuget.org/v3/index.json
cd ../..

# Dart → pub.dev
cd sdks/dart
dart pub publish
cd ../..

echo "All SDKs published at version $VERSION"

SDK Usage Examples

// PHP SDK
use HostUK\HostHub\Api\WorkspacesApi;
use HostUK\HostHub\Configuration;

$config = Configuration::getDefaultConfiguration()
    ->setApiKey('Authorization', 'Bearer hk_xxxxxxxx_xxxxx...');

$api = new WorkspacesApi(config: $config);

$workspaces = $api->listWorkspaces();
foreach ($workspaces as $workspace) {
    echo $workspace->getName();
}
// TypeScript SDK
import { WorkspacesApi, Configuration } from '@host-uk/hosthub-sdk';

const config = new Configuration({
  apiKey: 'Bearer hk_xxxxxxxx_xxxxx...',
});

const api = new WorkspacesApi(config);

const workspaces = await api.listWorkspaces();
workspaces.forEach(ws => console.log(ws.name));
# Python SDK
from hosthub import Configuration, WorkspacesApi

config = Configuration()
config.api_key['Authorization'] = 'Bearer hk_xxxxxxxx_xxxxx...'

api = WorkspacesApi(configuration=config)

workspaces = api.list_workspaces()
for ws in workspaces:
    print(ws.name)

Documentation Site (api.host.uk.com)

Site Structure

api.host.uk.com/
├── /                    # Landing page (getting started)
├── /docs                # Swagger UI (interactive)
├── /reference           # ReDoc (beautiful reference)
├── /openapi.json        # Raw OpenAPI spec
├── /openapi.yaml        # YAML version
├── /sdks                # SDK download page
│   ├── /php             # PHP SDK + docs
│   ├── /typescript      # TypeScript SDK + docs
│   └── /python          # Python SDK + docs
├── /guides              # Integration guides
│   ├── /authentication  # Auth guide
│   ├── /webhooks        # Webhook setup
│   └── /rate-limits     # Rate limiting info
└── /changelog           # API changelog

Landing Page Content

# Host Hub API

Build integrations with Host Hub using our REST API.

## Quick Start

1. **Get an API Key**
   Navigate to Settings → API Keys in your workspace dashboard.

2. **Make Your First Request**
   ```bash
   curl https://api.host.uk.com/v1/workspaces \
     -H "Authorization: Bearer hk_your_api_key"
  1. Use an SDK

Looking for Agent Integration?

For AI agent and MCP server integration, visit mcp.host.uk.com.


### Deployment

```yaml
# Separate static site or Laravel routes
# Option A: Static site (Astro/Next.js) pulling openapi.json
# Option B: Laravel routes serving documentation

# routes/api-docs.php (if using Laravel)
Route::domain('api.host.uk.com')->group(function () {
    Route::get('/', [ApiDocsController::class, 'landing']);
    Route::get('/docs', [ApiDocsController::class, 'swagger']);
    Route::get('/reference', [ApiDocsController::class, 'redoc']);
    Route::get('/openapi.json', [ApiDocsController::class, 'openApiJson']);
    Route::get('/openapi.yaml', [ApiDocsController::class, 'openApiYaml']);
    Route::get('/sdks', [ApiDocsController::class, 'sdks']);
    Route::get('/sdks/{language}', [ApiDocsController::class, 'sdkDownload']);
});

Rate Limiting

// config/api.php
return [
    'rate_limits' => [
        'default' => [
            'requests' => 1000,
            'per_minutes' => 60,
        ],
        'authenticated' => [
            'requests' => 5000,
            'per_minutes' => 60,
        ],
        'by_tier' => [
            'starter' => ['requests' => 1000, 'per_minutes' => 60],
            'pro' => ['requests' => 5000, 'per_minutes' => 60],
            'agency' => ['requests' => 20000, 'per_minutes' => 60],
        ],
    ],
];

// Rate limit headers included in all responses:
// X-RateLimit-Limit: 5000
// X-RateLimit-Remaining: 4987
// X-RateLimit-Reset: 1704067200

Error Responses

// Standard error format
{
  "error": "validation_error",
  "message": "The given data was invalid.",
  "details": {
    "name": ["The name field is required."],
    "slug": ["The slug has already been taken."]
  }
}

// Error codes
{
  "error": "unauthorized",           // 401 - Missing/invalid auth
  "error": "forbidden",              // 403 - No permission
  "error": "not_found",              // 404 - Resource not found
  "error": "validation_error",       // 422 - Invalid input
  "error": "rate_limit_exceeded",    // 429 - Too many requests
  "error": "internal_error",         // 500 - Server error
  "error": "entitlement_exceeded",   // 403 - Plan limit reached
}

Webhooks

// Webhook events
'workspace.created'
'workspace.updated'
'workspace.deleted'
'subscription.created'
'subscription.updated'
'subscription.cancelled'
'invoice.created'
'invoice.paid'
'invoice.failed'
'biolink.created'
'biolink.updated'
'link.created'
'link.clicked'  // High volume - opt-in only

// Webhook payload
{
  "id": "evt_123456",
  "type": "subscription.updated",
  "created_at": "2024-12-31T12:00:00Z",
  "data": {
    "subscription": { ... }
  },
  "workspace_id": 123
}

// Signature verification
$signature = hash_hmac('sha256', $payload, $webhookSecret);
// Compare with X-HostHub-Signature header

MCP Intersection Note

The REST API and MCP tools share the same underlying services:

┌──────────────────┐     ┌──────────────────┐
│   REST API       │     │   MCP Tools      │
│ api.host.uk.com  │     │ mcp.host.uk.com  │
└────────┬─────────┘     └────────┬─────────┘
         │                        │
         └──────────┬─────────────┘
                    ▼
         ┌──────────────────┐
         │  Service Layer   │
         │  (Laravel)       │
         └──────────────────┘

PHP applications may call REST endpoints directly. AI agents should prefer the MCP interface at mcp.host.uk.com for:

  • Structured tool calling
  • Entitlement-aware server discovery
  • Agent-optimized response formats

Implementation Phases

Phase 1: Foundation

  • Install Scramble
  • Configure API versioning
  • Create API key model and migration
  • Implement API key authentication guard
  • Set up rate limiting

Phase 2: Core Endpoints

  • Auth endpoints (token exchange)
  • Workspace CRUD
  • Entitlement checking
  • Member management

Phase 3: Product Endpoints

  • Biolinks CRUD
  • Short links CRUD
  • QR codes CRUD
  • Analytics endpoints

Phase 4: Commerce Endpoints

  • Subscription management
  • Invoice listing
  • Payment methods

Phase 5: Documentation Site

  • Deploy api.host.uk.com
  • Swagger UI integration
  • ReDoc integration
  • SDK download pages

Phase 6: SDK Generation

  • Set up OpenAPI Generator
  • Generate PHP SDK
  • Generate TypeScript SDK
  • Generate Python SDK
  • Publish to package registries

Phase 7: Webhooks

  • Webhook endpoint management
  • Event dispatching
  • Delivery tracking
  • Retry logic

Files to Create/Modify

New Files

app/
├── Http/
│   ├── Controllers/Api/V1/
│   │   ├── AuthController.php
│   │   ├── WorkspaceController.php
│   │   ├── EntitlementController.php
│   │   ├── BiolinkController.php
│   │   ├── LinkController.php
│   │   ├── QrCodeController.php
│   │   ├── SubscriptionController.php
│   │   ├── InvoiceController.php
│   │   └── WebhookController.php
│   ├── Middleware/
│   │   └── AuthenticateApiKey.php
│   ├── Resources/
│   │   ├── WorkspaceResource.php
│   │   ├── BiolinkResource.php
│   │   ├── LinkResource.php
│   │   └── ... (all API resources)
│   └── Requests/Api/
│       └── ... (all form requests)
├── Models/
│   ├── ApiKey.php
│   └── WebhookEndpoint.php
config/
├── scramble.php
└── api.php
routes/
├── api_v1.php
└── api-docs.php
database/migrations/
├── create_api_keys_table.php
└── create_webhook_endpoints_table.php
scripts/
└── generate-sdks.sh
sdk-config/
├── php.yaml
├── typescript.yaml
└── python.yaml

Modified Files

  • routes/api.php - Include versioned routes
  • app/Http/Kernel.php - Register API middleware
  • composer.json - Add Scramble dependency

Created: 2024-12-31 Status: Planning Destination: api.host.uk.com