openapi: 3.1.0 info: title: AI Usage Disclosure API version: 1.6.3 description: Stateless multilingual badge, declaration and validation API with optional licensed presentation capabilities. servers: - url: https://ai.example.org paths: /badge/{preset}.svg: get: summary: Render a standard preset badge parameters: - name: preset in: path required: true schema: {type: string, enum: [no-ai, research, summary, full]} - {$ref: '#/components/parameters/language'} - {$ref: '#/components/parameters/theme'} - {$ref: '#/components/parameters/style'} - {name: link, in: query, schema: {type: string, description: Use auto to link to the generated declaration page.}} responses: "200": description: SVG badge content: image/svg+xml: {schema: {type: string}} /v1/badge.svg: get: summary: Render an SVG badge from structured parameters description: Custom labels and colours require the custom_badge capability. parameters: - {$ref: '#/components/parameters/extent'} - {$ref: '#/components/parameters/language'} - {name: preset, in: query, schema: {type: string, enum: [no-ai, research, summary, full]}} - {$ref: '#/components/parameters/legalContext'} - {$ref: '#/components/parameters/theme'} - {$ref: '#/components/parameters/style'} - {name: link, in: query, schema: {type: string}} - {name: badgeLabel, in: query, description: Licensed feature custom_badge, schema: {type: string, maxLength: 40}} - {name: badgeMessage, in: query, description: Licensed feature custom_badge, schema: {type: string, maxLength: 80}} - {name: leftColor, in: query, description: Licensed feature custom_badge, schema: {type: string, pattern: '^#[0-9A-Fa-f]{6}$'}} - {name: rightColor, in: query, description: Licensed feature custom_badge, schema: {type: string, pattern: '^#[0-9A-Fa-f]{6}$'}} responses: "200": description: SVG badge content: image/svg+xml: {schema: {type: string}} "403": {$ref: '#/components/responses/ProRequired'} /declaration: get: summary: Render a human-readable declaration page parameters: - {$ref: '#/components/parameters/preset'} - {$ref: '#/components/parameters/extent'} - {$ref: '#/components/parameters/language'} - {$ref: '#/components/parameters/component'} - {$ref: '#/components/parameters/activities'} - {$ref: '#/components/parameters/review'} - {$ref: '#/components/parameters/legalContext'} - {name: responsibleRole, in: query, schema: {type: string, enum: [publisher, other]}} - {name: responsible, in: query, schema: {type: string, maxLength: 200}} - {name: responsibleUrl, in: query, schema: {type: string, format: uri}} - {$ref: '#/components/parameters/legalContext'} - {$ref: '#/components/parameters/assurance'} - {$ref: '#/components/parameters/customTitle'} - {$ref: '#/components/parameters/customDescription'} - {$ref: '#/components/parameters/badgeLabel'} - {$ref: '#/components/parameters/badgeMessage'} - {$ref: '#/components/parameters/leftColor'} - {$ref: '#/components/parameters/rightColor'} responses: "200": {description: Human-readable HTML declaration} "403": {$ref: '#/components/responses/ProRequired'} /v1/declaration.json: get: summary: Generate a JSON-LD declaration from query parameters parameters: - {$ref: '#/components/parameters/preset'} - {$ref: '#/components/parameters/extent'} - {$ref: '#/components/parameters/language'} - {$ref: '#/components/parameters/component'} - {$ref: '#/components/parameters/activities'} - {$ref: '#/components/parameters/review'} - {name: subject, in: query, schema: {type: string, format: uri}} - {name: responsibleRole, in: query, schema: {type: string, enum: [publisher, other]}} - {name: responsible, in: query, schema: {type: string, maxLength: 200}} - {name: responsibleUrl, in: query, schema: {type: string, format: uri}} - {$ref: '#/components/parameters/assurance'} - {$ref: '#/components/parameters/customTitle'} - {$ref: '#/components/parameters/customDescription'} - {$ref: '#/components/parameters/badgeLabel'} - {$ref: '#/components/parameters/badgeMessage'} - {$ref: '#/components/parameters/leftColor'} - {$ref: '#/components/parameters/rightColor'} responses: "200": description: JSON-LD declaration content: application/ld+json: schema: {$ref: './schema/declaration.schema.json'} "403": {$ref: '#/components/responses/ProRequired'} /v1/validate: post: summary: Validate an AI usage declaration requestBody: required: true content: application/json: schema: {$ref: './schema/declaration.schema.json'} responses: "200": {description: Valid declaration} "422": {description: Validation failed} /v1/capabilities: get: summary: Return edition, licensed features and supported languages responses: "200": description: Runtime capabilities content: application/json: schema: type: object properties: license: type: object required: [edition, licensed, features] additionalProperties: false properties: edition: {type: string} licensed: {type: boolean} features: type: array items: {type: string} limits: type: object additionalProperties: {type: integer, format: int64} expiresAt: {type: string, format: date-time} supportedLanguages: type: array items: {type: string} /healthz: get: summary: Liveness endpoint responses: {"200": {description: Healthy}} /readyz: get: summary: Readiness endpoint responses: {"200": {description: Ready}} components: parameters: preset: name: preset in: query schema: {type: string, enum: [no-ai, research, summary, full]} extent: name: extent in: query schema: {type: string, enum: [none, assisted, partial, mostly, full], default: assisted} language: name: lang in: query schema: {type: string, enum: [de, en, fr, es, it, nl, pt, pl]} component: name: component in: query schema: {type: string, enum: [text, coverImage, image, audio, video, code, other], default: text} activities: name: activities in: query schema: {type: string, description: Comma-separated activity identifiers.} review: name: review in: query schema: {type: string, enum: [none, basic, editorial, expert], default: none} legalContext: name: legalContext in: query description: Comma-separated self-classification for Article 50 context. This is supporting metadata, not an automatic legal determination. schema: {type: string, example: publicInterestText} assurance: name: assurance in: query description: Evidence basis for the declaration. schema: {type: string, enum: [selfDeclared, technicallyRecorded, signed, verified], default: selfDeclared} theme: name: theme in: query schema: {type: string, enum: [mono, color, emoji], default: color} style: name: style in: query schema: {type: string, enum: [flat, flat-square], default: flat} customTitle: name: customTitle in: query description: Licensed feature custom_text schema: {type: string, maxLength: 120} customDescription: name: customDescription in: query description: Licensed feature custom_text schema: {type: string, maxLength: 500} badgeLabel: name: badgeLabel in: query description: Licensed feature custom_badge schema: {type: string, maxLength: 40} badgeMessage: name: badgeMessage in: query description: Licensed feature custom_badge schema: {type: string, maxLength: 80} leftColor: name: leftColor in: query description: Licensed feature custom_badge schema: {type: string, pattern: '^#[0-9A-Fa-f]{6}$'} rightColor: name: rightColor in: query description: Licensed feature custom_badge schema: {type: string, pattern: '^#[0-9A-Fa-f]{6}$'} responses: ProRequired: description: A valid licensed capability is required content: application/problem+json: schema: type: object properties: code: {const: pro_feature_required} status: {const: 403} detail: {type: string}