Skip to main content

SDK Reference

Early Draft

This specification is at an early draft stage. Ideas are open for change and debate. A lot of the content was developed with the help of Claude AI.

SDK Reference

Installation

# Python
pip install vera-publisher-sdk

# Node.js / Next.js
npm install @vera-browser/publisher-sdk

# PHP (Composer)
composer require vera-browser/publisher-sdk

# WordPress
wp plugin install vera-browser-publisher

Unified Gateway

The central SDK entry point: automatic routing to VRP or standard.

from vera_sdk import VeraGateway, PublisherConfig

config = PublisherConfig(
publisher_key = "spiegel",
domain = "some-publisher.news",
vera_api_key = "vera_live_...",
)

gateway = VeraGateway(config)

def article_view(request, slug):
article = get_article(slug)
return gateway.handle(request, article)

Python / Django

from vera_sdk import VeraContext, AccessOptions, VeraMiddleware

# settings.py
MIDDLEWARE = ["vera_sdk.middleware.VeraMiddleware", ...]

# views.py
def article_view(request, slug):
article = Article.objects.get(slug=slug)
requestor = request.vera.requestor_type # set by VeraMiddleware

if requestor == "vera_human":
vera = request.vera
if vera.has_subscription("spiegel"):
return HttpResponse(render_vera_template(article), status=200)
r = HttpResponse(render_vera_preview(article), status=402)
r["X-Vera-Access"] = AccessOptions.choice(
ppr_price=0.49, subscription_key="spiegel"
).to_json()
return r

if requestor == "ai_agent":
return JsonResponse({"error": "licensed_content"}, status=402)

if requestor == "standard_browser":
return render_standard(request, article)

return HttpResponse(status=403)

Node.js / Next.js: Edge Middleware

// middleware.ts
import { VeraEdgeMiddleware } from "@vera-browser/publisher-sdk/edge";

export const config = { matcher: "/article/:path*" };

export default VeraEdgeMiddleware({
publisherKey: "spiegel",
apiKey: process.env.VERA_API_KEY!,

onVeraAuthenticated: async (request, vera) => {
if (vera.hasSubscription("spiegel")) {
return rewriteTo(request, "?vera=clean");
}
return vera.paymentRequired({
options: [
{ type: "ppr", price: 0.49, currency: "EUR" },
{ type: "subscription", key: "spiegel" },
{ type: "ad_supported" },
],
});
},

onVeraAnonymous: async (request) =>
rewriteTo(request, "?vera=clean&auth=required"),

onAiAgent: async () =>
new Response(JSON.stringify({ error: "licensed_content" }), { status: 402 }),

onUnknownBot: async () => new Response("Forbidden", { status: 403 }),
onStandardBrowser: async (request) => NextResponse.next(),
});

PHP / WordPress Plugin

<?php
define('VERA_PUBLISHER_KEY', 'spiegel');

add_action('template_redirect', 'vera_gateway');

function vera_gateway(): void {
if (!is_singular('post')) return;

$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';

// Vera browser
if (str_starts_with($ua, 'Vera/')) {
$token = $_SERVER['HTTP_X_VERA_TOKEN'] ?? null;
$vera = vera_validate_token($token, get_site_url());

if ($vera && in_array(VERA_PUBLISHER_KEY, $vera['subscriptions'] ?? [])) {
add_filter('template_include', fn() => VERA_TEMPLATE_PATH);
return;
}
http_response_code(402);
header('X-Vera-Access: ' . vera_access_options_json());
add_filter('template_include', fn() => VERA_PREVIEW_TEMPLATE_PATH);
return;
}

// AI agent
if (vera_is_agent($ua)) {
http_response_code(402);
header('Content-Type: application/json');
echo json_encode(['error' => 'licensed_content']);
exit;
}

// Unknown bot
if (vera_is_unknown_bot($ua)) { http_response_code(403); exit; }

// Standard browser: continue normally
}

function vera_is_agent(string $ua): bool {
$agents = ['GPTBot', 'ClaudeBot', 'anthropic-ai', 'PerplexityBot', 'CCBot', 'Googlebot'];
foreach ($agents as $a) {
if (stripos($ua, $a) !== false) return true;
}
return false;
}
?>

API Reference: VeraContext

class VeraContext:
# Classification
requestor_type: RequestorType # VERA_HUMAN | AI_AGENT | STANDARD_BROWSER | UNKNOWN_BOT
is_vera: bool
is_agent: bool
mode: str # "standard" | "vera_anonymous" | "vera_authenticated" | "vera_invalid"

# Vera-specific (only when is_vera=True)
subscriptions: list[str] # Active subscription keys
ppr_balance: float # Pay-per-read balance in EUR
consent_scope: list[str] # Granted consent categories
network_verified: bool # Network verification signal valid
human_score: float # 0.0–1.0
client_version: str # e.g. "1.2.4"

def has_subscription(self, publisher_key: str) -> bool: ...
def has_consent(self, scope: str) -> bool: ...
def is_human(self, threshold: float = 0.85) -> bool: ...


class AccessOptions:
@staticmethod
def ppr(price: float, currency: str = "EUR") -> "AccessOptions": ...

@staticmethod
def subscription(key: str) -> "AccessOptions": ...

@staticmethod
def choice(ppr_price: float, subscription_key: str,
ad_supported: bool = False) -> "AccessOptions": ...

def to_json(self) -> str: ...