API Hub Integration

Beta

API Hub Overview

API Hub is a standalone Node.js service for teams whose language or platform does not yet have a native Fynlink SDK.

Because of Fynlink's end-to-end encrypted architecture, a universal direct REST surface is not offered for every client environment. API Hub bridges that gap by exposing clean REST endpoints while executing official SDK flows internally, so you get consistent behavior, security, and responses across stacks.

Introduction

Why API Hub

If your language of choice does not have an official SDK, API Hub gives you a production-ready fallback. Integrate once over REST and keep the same core behavior expected from official client flows.

Language-agnostic integration

Call API Hub from Python, PHP, Go, Java, shell, or no-code tools with the same REST contract.

Single integration point

Keep API traffic centralized behind one proxy service instead of duplicating client logic across apps.

Architecture-compatible

API Hub executes official SDK flows internally instead of reverse-engineered direct backend calls.

How It Works

API Hub is intentionally thin and proxy-oriented. It does not replace upstream business logic.

Step 1

Client sends REST request

Any language or tool can call API Hub over HTTP.

Step 2

API Hub processes request

Auth, schema validation, routing, and request/response shaping happen here.

Step 3

Fynlink API executes upstream logic

Official SDK flow is used and normalized JSON is returned to the caller.

API Hub handles transport, auth, and validation. Backend business rules and protected controls remain upstream.

Security Model

Security first design
  • Optional proxy bearer token auth for client-to-hub access control.
  • Strict request schema validation for POST and PATCH operations.
  • Security headers and standardized error responses with request IDs.
  • No reimplementation of protected upstream internals.

Getting Started

Install

Use the official prebuilt Docker image directly.

bash
docker pull ghcr.io/fynlink/api-hub:latest

Run

bash
curl -fsSL https://raw.githubusercontent.com/FynLink/api-hub/main/.env.example -o .env
bash
docker run -d --name fyn-api-hub \
--env-file .env \
-p 8787:8787 \
--restart unless-stopped \
ghcr.io/fynlink/api-hub:latest

Local URLs & Swagger UI

Built inSwagger UIOpenAPI 3.0

API Hub includes interactive Swagger docs out of the box. Use the UI for manual testing and use the OpenAPI JSON for client generation and tooling integration.

URLPurpose
http://localhost:8787/healthLiveness check endpoint.
http://localhost:8787/openapi.jsonOpenAPI 3.0 document for all API Hub routes.
http://localhost:8787/docsBuilt-in Swagger UI, powered by OpenAPI.
http://localhost:8787/v1Endpoint index summary from API Hub.
http://localhost:8787/v1/infoTeam/account bootstrap payload (optionally force refresh).

Swagger and OpenAPI endpoints are available immediately after startup.

AI Tools Integration

Best Path: Use MCP

RecommendedBest for AI tools

For AI assistants and agent platforms, MCP is the right integration model. It gives structured tools, clear permission boundaries, and predictable tool-calling behavior.

Use the dedicated MCP guide for end-to-end setup:

Alternative Path: OpenAPI via API Hub

If your AI platform supports OpenAPI/Swagger tool import but not MCP, API Hub can still be used effectively because it exposes an OpenAPI document at /openapi.json.

Setup ItemWhat to provide
Schema URLhttps://api-hub.example.com/openapi.json
Base URLhttps://api-hub.example.com
Auth headerAuthorization: Bearer <API_HUB_BEARER_TOKEN>
Docs UI (optional)https://api-hub.example.com/docs
json
{
  "openapi": "https://api-hub.example.com/openapi.json",
  "server": "https://api-hub.example.com",
  "headers": {
    "Authorization": "Bearer <API_HUB_BEARER_TOKEN>"
  }
}

Keep token scope minimal and expose API Hub only over HTTPS in production.

Workflow Examples for AI Agents

These are common AI tasks mapped to API Hub operations. Keep this section conceptual and use the full request examples in the REST API section below.

AI TaskEndpointMethod
Create campaign short link/v1/linksPOST
Fetch 30-day performance trend/v1/analytics/links/:id/timeseriesGET
Verify branded domain setup/v1/domains/:id/verifyPOST
For exact payloads and multi-language requests, use the detailed endpoint examples under REST API:Links, Domains, and Analytics sections.

Configuration

Hub Config

VariableDescription
PORTPort used by API Hub. Default: 8787
NODE_ENVRuntime mode: development, test, production
API_HUB_BEARER_TOKENOptional token for caller authentication
API_HUB_CORS_ORIGINCORS origin. Default: *

Upstream SDK Config

VariableDescription
FYN_API_TOKENRequired upstream API token used by @fynlink/sdk
FYN_SECRET_KEYRequired for encrypted read/list/update flows
FYN_API_URLOptional upstream base URL
FYN_TIMEOUT_MSUpstream timeout in milliseconds
FYN_RETRY_MAX_ATTEMPTSSDK retry max attempts
FYN_RETRY_INITIAL_DELAY_MSSDK retry initial delay in milliseconds
FYN_CACHE_ENABLEDEnable SDK cache
FYN_CACHE_TTL_MSSDK cache TTL in milliseconds
FYN_CACHE_STORAGESDK cache storage: memory or disk
FYN_CACHE_PATHDisk cache file path

Optional Create Defaults

VariableDescription
FYN_DEFAULT_CREATE_DOMAINFallback domain for links.create when omitted
FYN_DEFAULT_CREATE_SAFE_MODEDefault safeMode for links.create
FYN_DEFAULT_CREATE_ANALYTICSDefault analytics mode for links.create
FYN_DEFAULT_CREATE_PRIVATE_LINKDefault privateLink for links.create
FYN_DEFAULT_CREATE_EXPIRY_SECONDSDefault expirySeconds for links.create

Production Deployment

Recommended Strategy

The current API Hub repository is built as a long-running Node.js service on Hono (@hono/node-server). The default production path is running the published GHCR image with Docker Compose, then placing it behind HTTPS via Nginx or your load balancer.

Production Hardening Checklist

Use this baseline before exposing API Hub to public or partner traffic.

ControlMinimum hardening requirement
Image versionPin API_HUB_IMAGE_TAG to a tested version tag (vX.Y.Z) instead of latest.
Inbound authSet API_HUB_BEARER_TOKEN and rotate it regularly.
CORS policySet API_HUB_CORS_ORIGIN to trusted origins only when browser clients are involved.
Secrets handlingStore FYN_API_TOKEN and FYN_SECRET_KEY in a secret manager; never commit them.
Transport securityExpose API Hub only over HTTPS with TLS terminated at reverse proxy or load balancer.
Network boundaryRestrict inbound access to approved source ranges and required ports only.
ObservabilityKeep /health checks, collect logs, and wire alerting for 4xx/5xx and restart spikes.
Release processPromote pinned image tags through staging before production rollout.

Platform Guides (Quick Notes)

VPS / Bare Metal logo

VPS / Bare Metal

Recommended

How: Run API Hub directly on your own VM or machine.

Setup: Use Node 20+, run via systemd/PM2, terminate TLS with Nginx/Caddy, and keep env vars + logs managed on host.

Railway logo

Railway

Recommended

How: Deploy as a Node web service.

Setup: Build: npm ci && npm run build. Start: npm run start. Configure env vars in Railway dashboard.

Render logo

Render

Recommended

How: Deploy as a Node web service.

Setup: Use the same Node build/start commands and set environment variables in Render service settings.

Fly.io logo

Fly.io

Recommended

How: Deploy as a container or Node app.

Setup: Keep one region close to your upstream backend and scale based on traffic patterns.

Cloudflare logo

Cloudflare

Adapter required

How: Use a Workers-target variant.

Setup: Reuse route contracts and switch to a Workers runtime adapter deployed through Wrangler.

Vercel logo

Vercel

Adapter required

How: Use a Functions-target variant.

Setup: Expose a Vercel adapter entrypoint and keep environment variables in Vercel project settings.

For Cloudflare/Vercel, keep this API contract the same and maintain a runtime-specific entrypoint. This keeps integration clients stable.

Upgrade & Rollout

Use these commands when you are operating API Hub in production and want to update images safely.

bash
# update to latest image (brief restart)
docker compose pull
docker compose up -d
bash
# pin to a specific version
API_HUB_IMAGE_TAG=v0.1.1 docker compose pull
API_HUB_IMAGE_TAG=v0.1.1 docker compose up -d
bash
# zero downtime (blue/green behind Nginx)
NEW_TAG=v0.1.1
docker pull ghcr.io/fynlink/api-hub:${NEW_TAG}

docker run -d --name fyn-api-hub-green \
--env-file .env \
-p 8788:8787 \
--restart unless-stopped \
ghcr.io/fynlink/api-hub:${NEW_TAG}

curl -fsS http://127.0.0.1:8788/health
# switch nginx upstream from :8787 to :8788, then reload
sudo nginx -s reload

docker stop fyn-api-hub && docker rm fyn-api-hub
docker rename fyn-api-hub-green fyn-api-hub

Docker (Hono Node)

Containerizing API Hub is the most portable production approach when using the current Node runtime implementation. The repository includes a production Dockerfile and a docker-compose.yml that defaults to the official GHCR image.

bash
# compose-based run (recommended)
docker compose pull
docker compose up -d

# local image build (optional)
docker build -t fyn-api-hub:latest .

Nginx Reverse Proxy

For production, terminate TLS at Nginx and proxy traffic to the Hono Node process on localhost.

bash
server {
listen 443 ssl http2;
server_name api-hub.example.com;

ssl_certificate /etc/letsencrypt/live/api-hub.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api-hub.example.com/privkey.pem;

location / {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
proxy_pass http://127.0.0.1:8787;
}
}

Pair this with process supervision (`systemd`, Docker restart policy, or managed platform process controls) and health checks on /health .

Authentication

Multi-LanguageShared Tabs

All tabbed examples on this page are synchronized to one selected language so you can switch once and continue reading without repeated tab changes.

LanguageRecommended HTTP clientInstall
Pythonrequestspip install requests
PHPguzzlehttp/guzzlecomposer require guzzlehttp/guzzle
Gonet/http (stdlib)No extra package required
SwiftURLSession (Foundation)No extra package required
KotlinOkHttpimplementation("com.squareup.okhttp3:okhttp:4.12.0")
Rustreqwest blocking clientcargo add reqwest --features blocking,rustls-tls

API Hub supports optional bearer authentication for inbound callers. If API_HUB_BEARER_TOKEN is set, every request to /v1/* must include an Authorization: Bearer ... header.

Authenticated Team Request

bash
curl "http://localhost:8787/v1/team" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Upstream authentication is handled separately through FYN_API_TOKEN and optional FYN_SECRET_KEY.

REST API

Endpoint Map

Base path: /v1

MethodPathDescription
GET/healthHealth check endpoint
GET/v1Service and endpoint index
GET/v1/infoGet account and domain info
POST/v1/linksCreate link
GET/v1/linksList links
GET/v1/links/:idGet link by ID
PATCH/v1/links/:idUpdate link fields
DELETE/v1/links/:idDelete link
POST/v1/domainsCreate domain
GET/v1/domainsList domains
GET/v1/domains/:idGet domain
PATCH/v1/domains/:idUpdate domain
POST/v1/domains/:id/verifyTrigger domain verification
DELETE/v1/domains/:idRemove domain
POST/v1/membersInvite member
GET/v1/membersList members
GET/v1/members/:idGet member
PATCH/v1/members/:idUpdate member role
DELETE/v1/members/:idRemove member
GET/v1/teamGet team profile
PATCH/v1/teamUpdate team name
GET/v1/analytics/links/:id/clicksLink click summary
GET/v1/analytics/links/:id/timeseriesLink time series metrics
GET/v1/analytics/links/:id/browsersBrowser breakdown
GET/v1/analytics/links/:id/devicesDevice breakdown
GET/v1/analytics/links/:id/countriesCountry breakdown
GET/v1/analytics/links/:id/referrersReferrer breakdown

Conventions

TopicBehavior
Content typeUse application/json for POST and PATCH request bodies.
AuthenticationOptional bearer auth at API Hub layer via Authorization header.
Request IDInclude x-request-id to propagate your own tracing ID.
Boolean query valuestrue/false and 1/0 are accepted.
CSV filterscountry, browser, device, referrer support comma-separated values.
Paginationpage and limit must be positive integers.
Payload strictnessUnknown JSON fields are rejected by schema validation.

Request ID Propagation Example

bash
curl "http://localhost:8787/v1/links?page=1&limit=20&safeMode=true" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN" \
-H "x-request-id: req_20260414_001"

Info

Use this endpoint to fetch team-level bootstrap information. Pass force=true to bypass SDK cache for that request.

MethodPathQueryDescription
GET/v1/infoforce (optional boolean)Returns account info and available domains.

Fetch Info (Forced Refresh)

bash
curl "http://localhost:8787/v1/info?force=true" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Domains

Create fieldTypeRequiredNotes
domainstringYesDomain to add to team.
descriptionstringNoOptional domain description.
notFoundUrlstringNoDestination for unmatched slugs.
rootRedirectstringNoRoot domain redirect target.
gpcbooleanNoGlobal Privacy Control behavior.
MethodPathNotes
GET/v1/domains?page=1&limit=20List domains
GET/v1/domains/:idGet one domain
PATCH/v1/domains/:idUpdate domain fields
POST/v1/domains/:id/verifyRun verification flow
DELETE/v1/domains/:idRemove domain

Create Domain

bash
curl -X POST "http://localhost:8787/v1/domains" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain": "links.example.com"
}'

List Domains

bash
curl "http://localhost:8787/v1/domains?page=1&limit=20" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Update Domain

bash
curl -X PATCH "http://localhost:8787/v1/domains/domain_123" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "Primary branded domain",
"gpc": true
}'

Verify Domain

bash
curl -X POST "http://localhost:8787/v1/domains/domain_123/verify" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Members

FieldTypeRequiredNotes
emailstringYesMember email for invitation.
roleadmin|member|readonlyYes (invite/update)Role to assign.
includeOwnerboolean queryNoInclude owner in list responses.

POST /v1/members and DELETE /v1/members/:id return 204 No Content on success.

Invite Member

bash
curl -X POST "http://localhost:8787/v1/members" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "dev@example.com",
"role": "member"
}'

List Members

bash
curl "http://localhost:8787/v1/members?includeOwner=true" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Update Member Role

bash
curl -X PATCH "http://localhost:8787/v1/members/member_123" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"role": "admin"
}'

Remove Member

bash
curl -X DELETE "http://localhost:8787/v1/members/member_123" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Team

MethodPathBodyDescription
GET/v1/team-Fetch team profile
PATCH/v1/team{ "name": "..." }Update team name

Get Team

bash
curl "http://localhost:8787/v1/team" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Update Team

bash
curl -X PATCH "http://localhost:8787/v1/team" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Growth Team"
}'

Analytics

EndpointDescription
/v1/analytics/links/:id/clicksTotal clicks and aggregate link metrics.
/v1/analytics/links/:id/timeseriesTime-bucketed analytics series.
/v1/analytics/links/:id/browsersBrowser distribution.
/v1/analytics/links/:id/devicesDevice distribution.
/v1/analytics/links/:id/countriesCountry distribution.
/v1/analytics/links/:id/referrersReferrer distribution.
QueryTypeNotes
startstringRange start (ISO datetime recommended).
endstringRange end (ISO datetime recommended).
granularityminute|hour|day|week|monthTimeseries interval.
countryCSV stringExample: US,IN,DE
browserCSV stringExample: Chrome,Firefox
deviceCSV stringExample: Desktop,Mobile
referrerCSV stringExample: google.com,news.ycombinator.com

Clicks Summary

bash
curl "http://localhost:8787/v1/analytics/links/link_123/clicks" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Timeseries

bash
curl "http://localhost:8787/v1/analytics/links/link_123/timeseries?start=2026-04-01T00:00:00Z&end=2026-04-14T23:59:59Z&granularity=day" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Country Breakdown

bash
curl "http://localhost:8787/v1/analytics/links/link_123/countries?start=2026-04-01T00:00:00Z&end=2026-04-14T23:59:59Z&country=US,IN,DE" \
-H "Authorization: Bearer $API_HUB_BEARER_TOKEN"

Errors

API Hub returns normalized non-2xx responses with an explicit error code and request ID for tracing.

json
{
  "error": {
    "code": "UPSTREAM_VALIDATION_ERROR",
    "message": "domain is required",
    "details": {}
  },
  "requestId": "req_20260414_001"
}
HTTPCodeWhen it happens
400VALIDATION_ERROR / HTTP_ERROR / UPSTREAM_VALIDATION_ERRORInvalid payload, malformed query, or upstream validation failure.
401UPSTREAM_AUTH_ERROR / HTTP_ERRORInvalid upstream token or missing/invalid API_HUB_BEARER_TOKEN.
403UPSTREAM_PERMISSION_ERRORToken lacks permissions for requested team resource.
404NOT_FOUND / UPSTREAM_NOT_FOUNDUnknown route or resource ID not found upstream.
429UPSTREAM_RATE_LIMITEDUpstream API rate limit reached.
500INTERNAL_ERRORUnexpected API Hub runtime error.
502UPSTREAM_ERRORGeneric upstream failure with unknown mapping.
504UPSTREAM_TIMEOUTUpstream timeout while SDK request is in progress.

API Hub is a proxy. Upstream validations and business rules remain on Fynlink backend. The hub focuses on secure transport, consistent REST interfaces, and operational ergonomics for multi-language client stacks.

E2EE
Your link data is encrypted, even before leaving the browser & can be decrypted only by you.
< 200ms
Average link redirection time, depends mainly on location of the end user.
99.99%
Uptime guarantee for our redirection services.
300+
For quick, uninterrupted URL redirection, our redirection service is available on all major cities worldwide.