diff --git a/README.md b/README.md index 8beb33f..6903300 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,6 @@ -# Scope3 Agentic Client +# Scope3 SDK -TypeScript client for the Scope3 Agentic API with AdCP webhook support. - -## Features - -- ๐Ÿš€ Full TypeScript support with generated types from OpenAPI schema -- ๐Ÿ“ฆ Complete API coverage for all Scope3 MCP tools -- ๐Ÿ” Bearer token authentication -- ๐Ÿ”Œ Official MCP SDK (`@modelcontextprotocol/sdk`) with HTTP streaming transport -- ๐Ÿช Optional webhook server for AdCP events -- โœจ Clean, intuitive API design -- ๐Ÿงช Comprehensive test coverage -- ๐Ÿ’ป **CLI tool** for all API resources (80+ commands) - -**Architecture:** This client uses the official `@modelcontextprotocol/sdk` to connect to the Scope3 MCP server at `https://api.agentic.scope3.com/mcp` via Streamable HTTP transport. This uses HTTP POST for sending messages and HTTP GET with Server-Sent Events for receiving messages, providing reliable bidirectional communication with automatic reconnection support. +TypeScript client for the Scope3 Agentic Platform. Supports three personas (buyer, brand, partner) with REST and MCP adapters. ## Installation @@ -21,341 +8,177 @@ TypeScript client for the Scope3 Agentic API with AdCP webhook support. npm install scope3 ``` -## Quick Start +## API Keys -The SDK provides two separate clients for different use cases: +Obtain your API key from the Scope3 dashboard: -### PlatformClient (for Brand Advertisers/Buyers) +- **Production:** [https://agentic.scope3.com](https://agentic.scope3.com) -> Manage API Keys +- **Staging:** [https://agentic.staging.scope3.com](https://agentic.staging.scope3.com) -> Manage API Keys -Use this client if you're a brand advertiser managing campaigns, creatives, and discovering media products. +## Environment URLs -```typescript -import { PlatformClient } from 'scope3'; +| Environment | URL | +|-------------|-----| +| Production | `https://api.agentic.scope3.com` | +| Staging | `https://api.agentic.staging.scope3.com` | -const platform = new PlatformClient({ - apiKey: process.env.SCOPE3_API_KEY, - environment: 'production', // or 'staging' -}); - -// List brand agents -const brandAgents = await platform.brandAgents.list(); +## Quick Start -// Create a campaign -const campaign = await platform.campaigns.create({ - prompt: 'Create a video campaign targeting tech enthusiasts', - brandAgentId: '123', -}); +The SDK uses a unified `Scope3Client` with a `persona` parameter to determine available resources. -// Discover media products -const products = await platform.mediaProducts.discover({ - channels: ['DIGITAL-DISPLAY'], - budget: { min: 10000, max: 50000 }, -}); -``` +### Buyer Persona -### PartnerClient (for DSPs/Publishers/Sales Agents) - -Use this client if you're a media partner managing tactics, media buys, and products. +For programmatic advertising -- manage advertisers, bundles, campaigns, and signals. ```typescript -import { PartnerClient } from 'scope3'; +import { Scope3Client } from 'scope3'; -const partner = new PartnerClient({ - apiKey: process.env.SCOPE3_API_KEY, - environment: 'production', // or 'staging' +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'buyer', }); -// Register a sales agent -const agent = await partner.agents.register({ - name: 'My DSP', - type: 'SALES', - endpointUrl: 'https://my-dsp.com/mcp', -}); +// List advertisers +const advertisers = await client.advertisers.list(); -// Create a media buy -const mediaBuy = await partner.mediaBuys.create({ - tacticId: 'tactic_123', - name: 'Q1 Campaign Buy', - budget: { amount: 100000, currency: 'USD' }, +// Create a bundle for inventory discovery +const bundle = await client.bundles.create({ + advertiserId: 'adv-123', + channels: ['display', 'video'], }); -// Execute media buy -await partner.mediaBuys.execute({ mediaBuyId: mediaBuy.id }); -``` - -## CLI Usage - -The CLI dynamically discovers available commands from the API server, ensuring it's always up-to-date. - -### Quick Start - -```bash -# Use with npx (no install needed) -npx scope3 --help - -# Or install globally -npm install -g scope3 -scope3 --help - -# Configure authentication -scope3 config set apiKey your_api_key_here - -# Configure environment (optional - defaults to production) -scope3 config set environment staging - -# Or use environment variables -export SCOPE3_API_KEY=your_api_key_here -export SCOPE3_ENVIRONMENT=staging # or 'production' +// Discover products in the bundle +const products = await client.bundles.discoverProducts(bundle.data.bundleId); -# Or use command-line flags -scope3 --environment staging list-tools - -# Discover available commands (80+ auto-generated) -scope3 list-tools - -# Examples -scope3 brand-agent list -scope3 campaign create --prompt "Q1 2024 Spring Campaign" --brandAgentId 123 -scope3 media-buy execute --mediaBuyId "buy_123" +// Add products to the bundle +await client.bundles.products(bundle.data.bundleId).add({ + products: [{ productId: 'prod-1', salesAgentId: 'sa-1', groupId: 'g-1', groupName: 'Group 1' }], +}); -# Switch environments on the fly -scope3 --environment production campaign list -scope3 --environment staging campaign list +// Create and execute a bundle campaign +const campaign = await client.campaigns.createBundle({ + advertiserId: 'adv-123', + bundleId: bundle.data.bundleId, + name: 'Q1 Campaign', + flightDates: { startDate: '2025-01-15', endDate: '2025-03-31' }, + budget: { total: 50000, currency: 'USD' }, +}); +await client.campaigns.execute(campaign.data.id); ``` -**Dynamic Updates:** Commands automatically stay in sync with API changes. No manual updates needed! - -## SDK Configuration +### Brand Persona -Both `PlatformClient` and `PartnerClient` accept the same configuration options: +For brand identity management -- manage brand manifests and metadata. ```typescript -const client = new PlatformClient({ - apiKey: 'your-api-key', - - // Option 1: Use environment (recommended) - environment: 'production', // 'production' or 'staging' (default: 'production') - - // Option 2: Use custom base URL (overrides environment) - baseUrl: 'https://custom-api.example.com', +const brandClient = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'brand', +}); - // Optional settings - timeout: 30000, // request timeout in ms - debug: false, // enable debug logging +const brands = await brandClient.brands.list(); +await brandClient.brands.create({ + manifestUrl: 'https://example.com/brand-manifest.json', }); ``` -### Environment URLs +### Partner Persona -- **Production**: `https://api.agentic.scope3.com` -- **Staging**: `https://api.agentic.staging.scope3.com` - -## API Resources - -### PlatformClient Resources - -```typescript -// Assets -await platform.assets.upload({ brandAgentId, assets: [...] }); -await platform.assets.list({ brandAgentId }); - -// Brand Agents -await platform.brandAgents.list(); -await platform.brandAgents.create({ name: 'My Brand' }); -await platform.brandAgents.get({ brandAgentId }); -await platform.brandAgents.update({ brandAgentId, name: 'Updated Name' }); -await platform.brandAgents.delete({ brandAgentId }); - -// Campaigns -await platform.campaigns.list({ status: 'ACTIVE' }); -await platform.campaigns.create({ prompt: '...', budget: {...} }); -await platform.campaigns.update({ campaignId, status: 'PAUSED' }); -await platform.campaigns.getSummary({ campaignId }); -await platform.campaigns.listTactics({ campaignId }); -await platform.campaigns.delete({ campaignId }); - -// Creatives -await platform.creatives.list({ brandAgentId }); -await platform.creatives.create({ brandAgentId, name: '...' }); -await platform.creatives.assign({ creativeId, campaignId }); - -// Tactics -await platform.tactics.list({ campaignId }); -await platform.tactics.create({ name: '...', campaignId }); -await platform.tactics.update({ tacticId, channelCodes: ['DIGITAL-AUDIO'] }); - -// Other Resources -// - platform.brandStandards - Brand safety standards -// - platform.brandStories - AI-powered audience definitions -// - platform.channels - Advertising channels -// - platform.mediaProducts - Media product discovery -// - platform.targeting - Geographic and demographic targeting -``` - -### PartnerClient Resources +For integration health monitoring. ```typescript -// Media Buys -await partner.mediaBuys.list({ tacticId }); -await partner.mediaBuys.create({ - tacticId, - name: '...', - products: [{ mediaProductId, salesAgentId }], - budget: { amount: 1000000 }, -}); -await partner.mediaBuys.execute({ mediaBuyId }); - -// Agents (Sales & Outcome) -await partner.agents.list(); -await partner.agents.list({ type: 'SALES' }); -await partner.agents.register({ - type: 'SALES', - name: '...', - endpointUrl: '...', - protocol: 'MCP', - authenticationType: 'API_KEY', +const partnerClient = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'partner', }); -await partner.agents.get({ agentId: '...' }); -await partner.agents.update({ agentId: '...', name: 'Updated Name' }); -await partner.agents.unregister({ agentId: '...' }); -// Other Resources -// - partner.products - Media product management -// - partner.webhooks - Webhook configuration +const health = await partnerClient.health.check(); ``` -## Webhook Server - -The client includes an optional webhook server for handling AdCP events: +## Configuration ```typescript -import { WebhookServer } from '@scope3/agentic-client'; - -const webhookServer = new WebhookServer({ - port: 3000, - path: '/webhooks', - secret: process.env.WEBHOOK_SECRET, // optional -}); - -// Register event handlers -webhookServer.on('campaign.created', async (event) => { - console.log('Campaign created:', event.data); +const client = new Scope3Client({ + apiKey: 'your-api-key', // Required: Bearer token + persona: 'buyer', // Required: 'buyer' | 'brand' | 'partner' + environment: 'production', // Optional: 'production' (default) | 'staging' + baseUrl: 'https://custom.com', // Optional: overrides environment + adapter: 'rest', // Optional: 'rest' (default) | 'mcp' + timeout: 30000, // Optional: request timeout in ms + debug: false, // Optional: enable debug logging }); - -webhookServer.on('media_buy.executed', async (event) => { - console.log('Media buy executed:', event.data); -}); - -// Catch all events -webhookServer.on('*', async (event) => { - console.log('Event received:', event.type); -}); - -// Start the server -await webhookServer.start(); -console.log(`Webhook server running at ${webhookServer.getUrl()}`); - -// Stop the server -await webhookServer.stop(); ``` -## Development +## CLI ```bash -# Install dependencies -npm install +# Configure +scope3 config set apiKey your_api_key_here +scope3 config set persona buyer -# Update schemas from upstream (downloads latest OpenAPI spec) -npm run update-schemas +# Use +scope3 advertisers list +scope3 advertisers get --id adv-123 +scope3 campaigns list --format json +scope3 bundles create --advertiserId adv-123 --channels display,video -# Type check without building -npm run type-check +# Override persona per-command +scope3 --persona brand brands list +scope3 --persona partner health +``` -# Build the project (includes type checking) -npm run build +## API Resources -# Run tests (includes pre-test type checking) -npm test +### Buyer Resources -# Run linter -npm run lint +- `client.advertisers` -- CRUD and sub-resources (brand, conversionEvents, creativeSets, testCohorts, reporting, mediaBuys) +- `client.buyerBrands` -- List brands available to the buyer +- `client.campaigns` -- list, get, createBundle, updateBundle, createPerformance, updatePerformance, createAudience, execute, pause +- `client.bundles` -- create, discoverProducts, browseProducts, products(bundleId) +- `client.signals` -- Discover signals -# Format code -npm run format +### Brand Resources -# Generate types from local OpenAPI spec -npm run generate-types -``` +- `client.brands` -- list, get, create, update, delete -### Type Safety +### Partner Resources -This client is **fully typed** with no `any` types: +- `client.health` -- Health check -- **Generated types** from OpenAPI spec using `openapi-typescript` -- **Strict TypeScript** configuration enabled -- **Pre-commit hooks** via Husky that run: - - Type checking (`tsc --noEmit`) - - Linting with auto-fix - - Code formatting -- **CI validation** on every PR: - - Type checking - - Linting - - Format checking - - Test execution - - Build verification +## skill.md Support -To update types when the upstream API changes: -```bash -npm run update-schemas +```typescript +// Get parsed skill documentation +const skill = await client.getSkill(); +console.log(skill.name, skill.version); +console.log(skill.commands); // Available API commands ``` -This downloads the latest OpenAPI spec and regenerates TypeScript types. - -## Contributing - -### Versioning and Releases - -This project uses [Changesets](https://github.com/changesets/changesets) for version management and automated NPM publishing. +## Webhook Server -#### Creating a Changeset +A `WebhookServer` class is available for handling AdCP events. See [docs/getting-started.md](docs/getting-started.md) for usage details. -When making changes that should be released, add a changeset: +## Development ```bash -npm run changeset +npm install +npm run type-check +npm run build +npm test +npm run lint ``` -Follow the prompts to: -1. Select the type of change (major, minor, patch) -2. Describe the changes for the changelog - -The changeset file will be committed with your PR. - -#### Release Process - -When a PR with changesets is merged to `main`: -1. The Release workflow creates a "Version Packages" PR -2. This PR updates package versions and generates changelogs -3. When the Version PR is merged, packages are automatically published to NPM - -**NPM Publishing:** Packages are published as `@scope3/agentic-client` with public access. +## Documentation -#### CI Requirements +- [Getting Started](docs/getting-started.md) +- [Buyer Guide](docs/buyer-guide.md) +- [Brand Guide](docs/brand-guide.md) +- [Partner Guide](docs/partner-guide.md) +- [CLI Reference](docs/cli-reference.md) -Every PR to `main` must include a changeset. The CI will fail if no changeset is detected. - -To bypass this check (for docs/config changes), create an empty changeset: -```bash -npm run changeset -# Select "patch" and leave the description empty -``` - -## Examples +## Contributing -See the `examples/` directory for more usage examples: -- `basic-usage.ts` - Basic API usage -- `create-campaign.ts` - Campaign creation workflow -- `webhook-server.ts` - Webhook server setup +This project uses [Changesets](https://github.com/changesets/changesets) for version management. When making changes that should be released, run `npm run changeset` and follow the prompts to describe your change. The changeset file is committed with your PR. ## License diff --git a/docs/brand-guide.md b/docs/brand-guide.md new file mode 100644 index 0000000..7f9b76f --- /dev/null +++ b/docs/brand-guide.md @@ -0,0 +1,129 @@ +# Brand Persona Guide + +The brand persona is designed for brand identity management within the Scope3 SDK. It provides full CRUD operations for managing brand profiles, including support for brand manifests that define visual identity, tone, and other brand attributes. + +## Setup + +Configure the client with the `brand` persona: + +```typescript +import { Scope3Client } from 'scope3'; + +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'brand', +}); +``` + +## Brand Management + +The brand persona supports the following operations: + +- **list** - Retrieve all brands with pagination support +- **get** - Retrieve a specific brand by ID +- **create** - Create a new brand using a manifest URL or inline manifest JSON +- **update** - Update an existing brand +- **delete** - Remove a brand + +## Manifest Formats + +When creating or updating a brand, you can provide the brand manifest in one of two formats: + +- **manifestUrl** - A URL pointing to a hosted JSON manifest file +- **manifestJson** - An inline JSON object containing the manifest data directly + +### Brand Manifest Schema + +The manifest supports the following fields: + +| Field | Description | +|---|---| +| `name` | Brand name | +| `url` | Brand website URL | +| `logos` | Array of logo objects with `url` and `tags` | +| `colors` | Object with color definitions (e.g., `primary`, `secondary`) | +| `fonts` | Object with font definitions (e.g., `primary`, `secondary`) | +| `tone` | Description of the brand voice and tone | +| `tagline` | Brand tagline or slogan | +| `assets` | Additional brand assets | +| `product_catalog` | Product catalog information | +| `disclaimers` | Legal disclaimers and compliance text | +| `industry` | Industry vertical | +| `target_audience` | Description of the target audience | +| `contact` | Contact information | +| `metadata` | Arbitrary key-value metadata | + +## Examples + +### List Brands + +```typescript +const brands = await client.brands.list(); + +for (const brand of brands.data) { + console.log(`${brand.id}: ${brand.name}`); +} +``` + +### Create with Manifest URL + +Use `manifestUrl` when your brand manifest is hosted externally: + +```typescript +await client.brands.create({ + manifestUrl: 'https://example.com/brand-manifest.json', +}); +``` + +### Create with Inline Manifest + +Use `manifestJson` to provide the manifest data directly: + +```typescript +await client.brands.create({ + manifestJson: { + name: 'Acme Corp', + url: 'https://acme.com', + logos: [{ url: 'https://acme.com/logo.png', tags: ['primary'] }], + colors: { primary: '#FF6600', secondary: '#333333' }, + fonts: { primary: 'Inter', secondary: 'Georgia' }, + tone: 'Professional and innovative', + tagline: 'Building the future', + industry: 'Technology', + target_audience: 'Enterprise decision makers', + }, +}); +``` + +### Get a Specific Brand + +```typescript +const brand = await client.brands.get('brand-123'); +console.log(brand.data.name); +``` + +### Update a Brand + +```typescript +await client.brands.update('brand-123', { + manifestJson: { name: 'Acme Corp Updated' }, +}); +``` + +### Delete a Brand + +```typescript +await client.brands.delete('brand-123'); +``` + +## Pagination + +List operations support pagination. Use the cursor returned in the response to fetch additional pages: + +```typescript +const firstPage = await client.brands.list(); + +if (firstPage.nextCursor) { + const secondPage = await client.brands.list({ cursor: firstPage.nextCursor }); +} +``` diff --git a/docs/buyer-guide.md b/docs/buyer-guide.md new file mode 100644 index 0000000..769733f --- /dev/null +++ b/docs/buyer-guide.md @@ -0,0 +1,224 @@ +# Buyer Persona Guide + +## Overview + +The buyer persona enables AI-powered programmatic advertising with: + +- Advertiser management +- Bundle-based inventory discovery +- 3 campaign types (bundle, performance, audience) +- Reporting and analytics + +## Setup + +```typescript +import { Scope3Client } from 'scope3'; + +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'buyer', +}); +``` + +## Full Buyer Workflow + +### Step 1: Create an Advertiser + +```typescript +const advertiser = await client.advertisers.create({ + name: 'Acme Corp', + description: 'Leading widget manufacturer', +}); +const advId = advertiser.data.id; +``` + +### Step 2: Link a Brand + +```typescript +const brand = client.advertisers.brand(advId); +await brand.link({ brandId: 'brand-123' }); +``` + +### Step 3: Create a Bundle for Inventory Discovery + +```typescript +const bundle = await client.bundles.create({ + advertiserId: advId, + channels: ['display', 'video'], + countries: ['US', 'UK'], + budget: 50000, +}); +const bundleId = bundle.data.bundleId; +``` + +### Step 4: Discover Products + +```typescript +const discovery = await client.bundles.discoverProducts(bundleId, { + groupLimit: 10, + productsPerGroup: 5, +}); + +// Browse the product groups +for (const group of discovery.data.productGroups) { + console.log(`${group.groupName}: ${group.productCount} products`); + for (const product of group.products) { + console.log(` - ${product.name} (${product.publisher}) $${product.cpm} CPM`); + } +} +``` + +### Step 5: Add Products to Bundle + +```typescript +const selectedProducts = discovery.data.productGroups[0].products.map(p => ({ + productId: p.productId, + salesAgentId: p.salesAgentId, + groupId: discovery.data.productGroups[0].groupId, + groupName: discovery.data.productGroups[0].groupName, +})); + +await client.bundles.products(bundleId).add({ products: selectedProducts }); +``` + +### Step 6: Create a Bundle Campaign + +```typescript +const campaign = await client.campaigns.createBundle({ + advertiserId: advId, + bundleId: bundleId, + name: 'Q1 Display Campaign', + flightDates: { startDate: '2025-01-15', endDate: '2025-03-31' }, + budget: { total: 50000, currency: 'USD', pacing: 'EVEN' }, +}); +``` + +### Step 7: Execute the Campaign + +```typescript +await client.campaigns.execute(campaign.data.id); +``` + +## Campaign Types + +### Bundle Campaigns + +Standard campaigns with pre-selected inventory bundles. + +```typescript +await client.campaigns.createBundle({ ... }); +await client.campaigns.updateBundle(id, { ... }); +``` + +### Performance Campaigns + +Goal-oriented campaigns with performance optimization. + +```typescript +await client.campaigns.createPerformance({ + advertiserId: advId, + name: 'ROAS Campaign', + flightDates: { startDate: '2025-01-15', endDate: '2025-03-31' }, + budget: { total: 100000, currency: 'USD' }, + performanceConfig: { + objective: 'ROAS', + goals: { targetRoas: 3.5 }, + }, +}); +``` + +### Audience Campaigns + +Signal-based audience targeting (coming soon). + +```typescript +await client.campaigns.createAudience({ ... }); +``` + +## Advertiser Sub-Resources + +Access sub-resources scoped to an advertiser. + +### Conversion Events + +```typescript +const events = client.advertisers.conversionEvents(advId); +await events.list(); +await events.create({ name: 'Purchase', type: 'PURCHASE', value: 50 }); +``` + +### Creative Sets + +```typescript +const sets = client.advertisers.creativeSets(advId); +await sets.list(); +await sets.create({ name: 'Holiday Creatives', type: 'display' }); +``` + +### Test Cohorts + +```typescript +const cohorts = client.advertisers.testCohorts(advId); +await cohorts.list(); +await cohorts.create({ name: 'A/B Test', splitPercentage: 50 }); +``` + +### Reporting + +```typescript +const reporting = client.advertisers.reporting(advId); +const report = await reporting.get({ days: 30 }); +console.log(`Total spend: $${report.data.totals.spend}`); +``` + +### Media Buys + +```typescript +const buys = client.advertisers.mediaBuys(advId); +const mediaBuys = await buys.list(); +``` + +## Signals + +```typescript +const signals = await client.signals.discover(); +``` + +## Buyer Brands + +List all brands available: + +```typescript +const brands = await client.buyerBrands.list(); +``` + +## Pagination + +All list methods support pagination: + +```typescript +const page1 = await client.advertisers.list({ take: 10, skip: 0 }); +const page2 = await client.advertisers.list({ take: 10, skip: 10 }); + +// Check pagination info +console.log(`Total: ${page1.pagination.total}, Has more: ${page1.pagination.hasMore}`); +``` + +## API Response Format + +All responses use a standard envelope: + +```typescript +// Single item +interface ApiResponse { + data: T; + error?: { code: string; message: string; details?: Record }; +} + +// Paginated list +interface PaginatedApiResponse { + data: T[]; + pagination: { total: number; take: number; skip: number; hasMore: boolean }; + error?: { code: string; message: string; details?: Record }; +} +``` diff --git a/docs/cli-reference.md b/docs/cli-reference.md new file mode 100644 index 0000000..2fdda19 --- /dev/null +++ b/docs/cli-reference.md @@ -0,0 +1,183 @@ +# CLI Reference + +Command-line interface reference for the Scope3 SDK. + +## Installation + +```bash +npm install -g scope3 +# or use with npx +npx scope3 --help +``` + +## Configuration + +### Setting Configuration Values + +```bash +# Set API key +scope3 config set apiKey your_api_key_here + +# Set default persona +scope3 config set persona buyer + +# Set environment +scope3 config set environment staging + +# View current config +scope3 config show +``` + +### Environment Variables + +Configuration can also be provided via environment variables. Environment variables take precedence over config file values but are overridden by command-line flags. + +```bash +export SCOPE3_API_KEY=your_api_key_here +export SCOPE3_ENVIRONMENT=staging +export SCOPE3_PERSONA=buyer +``` + +## Global Options + +| Option | Description | +|---|---| +| `--api-key ` | API key (overrides config and environment variable) | +| `--persona ` | Persona to use: `buyer`, `brand`, `partner` (overrides config and environment variable) | +| `--environment ` | Target environment: `production`, `staging` | +| `--base-url ` | Custom API base URL | +| `--format ` | Output format: `table` (default), `json`, `yaml` | +| `--debug` | Enable debug logging | +| `--version` | Show version number | +| `--help` | Show help information | + +## Buyer Commands + +The buyer persona is the default. The following commands are available without specifying `--persona`. + +### Advertisers + +```bash +# List all advertisers +scope3 advertisers list + +# Get a specific advertiser +scope3 advertisers get --id + +# Create an advertiser +scope3 advertisers create --name "Acme Corp" + +# Update an advertiser +scope3 advertisers update --id --name "New Name" + +# Delete an advertiser +scope3 advertisers delete --id +``` + +### Campaigns + +```bash +# List all campaigns +scope3 campaigns list + +# Get a specific campaign +scope3 campaigns get --id + +# Create a bundle campaign +scope3 campaigns create-bundle --advertiserId --bundleId --name "Campaign" ... + +# Create a performance campaign +scope3 campaigns create-performance --advertiserId --name "Perf Campaign" ... + +# Execute a campaign +scope3 campaigns execute --id + +# Pause a campaign +scope3 campaigns pause --id +``` + +### Bundles + +```bash +# Create a bundle +scope3 bundles create --advertiserId --channels display,video + +# Discover products for a bundle +scope3 bundles discover-products --bundleId + +# List products in a bundle +scope3 bundles list-products --bundleId + +# Add products to a bundle +scope3 bundles add-products --bundleId --products '[...]' +``` + +### Brands + +```bash +# List brands (buyer context) +scope3 brands list +``` + +## Brand Commands + +Brand commands require the `brand` persona. Use the `--persona brand` flag or set the persona in your configuration. + +```bash +# List all brands +scope3 --persona brand brands list + +# Get a specific brand +scope3 --persona brand brands get --id + +# Create a brand with a manifest URL +scope3 --persona brand brands create --manifestUrl "https://..." + +# Delete a brand +scope3 --persona brand brands delete --id +``` + +## Partner Commands + +Partner commands require the `partner` persona. + +```bash +# Check API health +scope3 --persona partner health +``` + +## Output Formats + +### Table (Default) + +The default output format renders results as a formatted table: + +```bash +scope3 advertisers list +``` + +``` +ID Name Status +---------- ------------ -------- +adv-001 Acme Corp active +adv-002 Widget Inc active +adv-003 FooBar Ltd paused +``` + +### JSON + +Use `--format json` for machine-readable JSON output: + +```bash +scope3 advertisers list --format json +``` + +```json +{ + "data": [ + { "id": "adv-001", "name": "Acme Corp", "status": "active" }, + { "id": "adv-002", "name": "Widget Inc", "status": "active" }, + { "id": "adv-003", "name": "FooBar Ltd", "status": "paused" } + ] +} +``` diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..9eb42c1 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,186 @@ +# Getting Started with the Scope3 SDK + +The `scope3` npm package provides a TypeScript/JavaScript client for the Scope3 Agentic Platform. It supports REST and MCP (Model Context Protocol) adapters, and organizes functionality around three personas: buyer, brand, and partner. + +## Installation + +```bash +npm install scope3 +``` + +## Getting Your API Key + +You need an API key to authenticate with the Scope3 platform. + +- **Production**: Go to [https://agentic.scope3.com](https://agentic.scope3.com), click **Manage API Keys**, and create a new key. +- **Staging**: Go to [https://agentic.staging.scope3.com](https://agentic.staging.scope3.com), click **Manage API Keys**, and create a new key. + +Store your API key securely. You will pass it to the client at initialization. + +## Choose Your Persona + +The SDK requires a persona to determine which API surface is available. There are three personas: + +| Persona | Use Case | +|------------|-----------------------------------------------------------------------------------------------| +| `buyer` | Programmatic advertising -- manage advertisers, campaigns, bundles, and inventory discovery. | +| `brand` | Brand identity management -- create and update brands with manifests. | +| `partner` | Integration partners -- health checks and coming-soon features. | + +Resources are scoped by persona. Attempting to access a resource outside of your chosen persona will throw an error at runtime. + +## Initialize the Client + +```typescript +import { Scope3Client } from 'scope3'; + +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'buyer', // or 'brand' or 'partner' +}); +``` + +## Configuration Options + +The full configuration interface: + +```typescript +interface Scope3ClientConfig { + /** API key (Bearer token) for authentication. Required. */ + apiKey: string; + + /** API persona -- buyer, brand, or partner. Required. */ + persona: 'buyer' | 'brand' | 'partner'; + + /** API version to use. Default: 'v2'. */ + version?: 'v1' | 'v2' | 'latest'; + + /** Environment. Default: 'production'. */ + environment?: 'production' | 'staging'; + + /** Custom base URL. Overrides the environment setting. */ + baseUrl?: string; + + /** Adapter type: 'rest' for HTTP, 'mcp' for AI agents. Default: 'rest'. */ + adapter?: 'rest' | 'mcp'; + + /** Request timeout in milliseconds. Default: 30000. */ + timeout?: number; + + /** Enable debug logging. Default: false. */ + debug?: boolean; +} +``` + +## Environment Setup + +The SDK targets two environments: + +| Environment | Base URL | +|---------------|---------------------------------------------| +| `production` | `https://api.agentic.scope3.com` | +| `staging` | `https://api.agentic.staging.scope3.com` | + +Production is the default. To use staging, either pass `environment: 'staging'` in the config or set environment variables: + +```bash +export SCOPE3_API_KEY=your_api_key_here +export SCOPE3_ENVIRONMENT=staging +``` + +Then in your code: + +```typescript +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'buyer', + environment: (process.env.SCOPE3_ENVIRONMENT as 'production' | 'staging') ?? 'production', +}); +``` + +## Your First Request + +### Buyer persona + +```typescript +import { Scope3Client } from 'scope3'; + +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'buyer', +}); + +// List advertisers +const advertisers = await client.advertisers.list(); +console.log('Advertisers:', advertisers); + +// Create a bundle for inventory discovery +const bundle = await client.bundles.create({ + advertiserId: 'adv_123', + channels: ['display'], +}); +console.log('Bundle:', bundle); +``` + +### Brand persona + +```typescript +import { Scope3Client } from 'scope3'; + +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'brand', +}); + +// List brands +const brands = await client.brands.list(); +console.log('Brands:', brands); +``` + +### Partner persona + +```typescript +import { Scope3Client } from 'scope3'; + +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'partner', +}); + +// Run a health check +const health = await client.health.check(); +console.log('Health:', health); +``` + +## Error Handling + +The SDK exports a `Scope3ApiError` class for structured error handling. It includes the HTTP status code, a message, and optional details. + +```typescript +import { Scope3Client, Scope3ApiError } from 'scope3'; + +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'buyer', +}); + +try { + const result = await client.advertisers.get('invalid-id'); +} catch (error) { + if (error instanceof Scope3ApiError) { + console.error(`API Error ${error.status}: ${error.message}`); + if (error.details) { + console.error('Details:', error.details); + } + } else { + throw error; + } +} +``` + +## Next Steps + +- [Buyer Guide](./buyer-guide.md) -- Full buyer workflow: advertisers, campaigns, bundles, and inventory discovery. +- [Brand Guide](./brand-guide.md) -- Brand identity management and manifests. +- [Partner Guide](./partner-guide.md) -- Partner integration and health checks. +- [CLI Reference](./cli-reference.md) -- Command-line interface usage. diff --git a/docs/partner-guide.md b/docs/partner-guide.md new file mode 100644 index 0000000..ccbf2b1 --- /dev/null +++ b/docs/partner-guide.md @@ -0,0 +1,40 @@ +# Partner Persona Guide + +The partner persona is designed for integration partners working with the Scope3 SDK. This persona is currently in early development, with additional capabilities planned for future releases. + +## Setup + +Configure the client with the `partner` persona: + +```typescript +import { Scope3Client } from 'scope3'; + +const client = new Scope3Client({ + apiKey: process.env.SCOPE3_API_KEY!, + persona: 'partner', +}); +``` + +## Currently Available + +### Health Check + +The health check endpoint allows partners to verify API connectivity and retrieve version information. + +```typescript +const health = await client.health.check(); +console.log(`Status: ${health.data.status}`); +console.log(`Version: ${health.data.version}`); +console.log(`API Version: ${health.data.apiVersion}`); +``` + +## Coming Soon + +The following features are planned for the partner persona and are not yet available: + +- **Agent Registration** - Register and manage AI agents that interact with the platform +- **Media Products** - Access and manage media product inventory +- **Webhooks** - Subscribe to real-time event notifications +- **Notifications** - Receive and manage platform notifications + +This guide will be updated as new partner capabilities are released. diff --git a/media-agent-openapi.yaml b/media-agent-openapi.yaml deleted file mode 100644 index 00bb81c..0000000 --- a/media-agent-openapi.yaml +++ /dev/null @@ -1,784 +0,0 @@ -openapi: 3.0.0 -info: - title: Media Agent Protocol - version: 1.0.0 - description: | - Protocol specification for media agents to implement on their own infrastructure. - - Media agents are autonomous systems that optimize media buying on behalf of advertisers. - When you build a media agent, you implement these endpoints on YOUR servers, and Scope3's - platform will call them to get tactic proposals, assign tactics, and send updates. - - This is similar to how sales agents work - you implement the protocol on your infrastructure, - not in Scope3's codebase. - -servers: - - url: https://media-agent.yourcompany.com - description: Your media agent server (you implement this) - -tags: - - name: Tactic Proposals - description: Endpoints Scope3 calls to get your tactic proposals - - name: Tactic Management - description: Endpoints for managing assigned tactics - - name: Tactic Updates - description: Notifications about changes to tactics you're managing - -paths: - /get-proposed-tactics: - post: - tags: [Tactic Proposals] - summary: Get tactic proposals from your agent - operationId: get_proposed_tactics - description: | - Scope3 calls this endpoint when setting up a campaign to ask what tactics - your agent can handle and how you would approach execution. - - Analyze the campaign and respond with proposed tactics, budget capacity, - and your pricing model. - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GetProposedTacticsRequest' - responses: - '200': - description: Tactic proposals from your agent - content: - application/json: - schema: - $ref: '#/components/schemas/GetProposedTacticsResponse' - '400': - description: Invalid request - '500': - description: Internal error - - /manage-tactic: - post: - tags: [Tactic Management] - summary: Accept or decline tactic assignment - operationId: manage_tactic - description: | - Scope3 calls this when your agent is assigned to manage a tactic. - You should acknowledge and begin setup, or decline if you can't fulfill it. - - The tactic context contains everything you need: budget, schedule, - targeting constraints, creatives, and any custom fields. - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ManageTacticRequest' - responses: - '200': - description: Acknowledgment of tactic assignment - content: - application/json: - schema: - $ref: '#/components/schemas/ManageTacticResponse' - '400': - description: Invalid request - - /tactic-context-updated: - post: - tags: [Tactic Updates] - summary: Notification of tactic changes - operationId: tactic_context_updated - description: | - Scope3 calls this when a tactic is modified by the user or their agent. - Changes may include budget adjustments, schedule changes, or other updates. - - Your agent MUST handle these changes as they may impact targeting, - delivery, or budget allocation. - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/TacticContextUpdatedRequest' - responses: - '200': - description: Acknowledged - '400': - description: Invalid request - - /tactic-creatives-updated: - post: - tags: [Tactic Updates] - summary: Notification of creative changes - operationId: tactic_creatives_updated - description: | - Scope3 calls this when creatives are added, removed, or modified for a tactic. - - Update your media buys to use the new creative assets. - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/TacticCreativesUpdatedRequest' - responses: - '200': - description: Acknowledged - '400': - description: Invalid request - - /tactic-feedback: - post: - tags: [Tactic Updates] - summary: Performance feedback from orchestrator - operationId: tactic_feedback - description: | - Scope3 sends performance feedback to help you optimize delivery. - - - deliveryIndex: 100 = on target, <100 = under-delivering, >100 = over-delivering - - performanceIndex: 100 = maximum, relative to target or other tactics - - Your agent MAY use this to adjust targeting, budget allocation, or other settings. - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/TacticFeedbackRequest' - responses: - '200': - description: Acknowledged - '400': - description: Invalid request - -components: - securitySchemes: - apiKey: - type: apiKey - in: header - name: X-API-Key - description: API key for authenticating Scope3's requests to your server - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - description: JWT bearer token for OAuth-based authentication - basic: - type: http - scheme: basic - description: Basic authentication with username/password - - schemas: - BudgetRange: - type: object - description: Budget range for campaign planning (buyer typically won't reveal full budget) - properties: - min: - type: number - description: Minimum budget available - example: 50000 - max: - type: number - description: Maximum budget available - example: 150000 - currency: - type: string - description: Currency for budget (ISO 4217 code) - default: USD - example: USD - - TacticPricing: - type: object - required: - - method - - rate - properties: - method: - type: string - enum: [passthrough, revshare, cost_per_unit] - description: How the media agent charges for this tactic (passthrough, revshare, or cost_per_unit) - example: revshare - rate: - type: number - description: Rate for the pricing method (e.g., 0.15 for 15% revshare, 2.50 for $2.50 CPM) - example: 0.15 - currency: - type: string - description: Currency for pricing (ISO 4217 code) - default: USD - example: USD - - CustomField: - type: object - properties: - fieldName: - type: string - description: Name of the custom field - example: targetVCPM - fieldType: - type: string - enum: [string, number, boolean, array, object] - description: Data type of the field - example: number - description: - type: string - description: Help text explaining what this field does - example: Target vCPM in USD - - GetProposedTacticsRequest: - type: object - required: - - campaignId - - seatId - properties: - campaignId: - type: string - description: Campaign ID - example: camp_123 - budgetRange: - $ref: '#/components/schemas/BudgetRange' - startDate: - type: string - format: date-time - description: Campaign start date in UTC (ISO 8601 format) - example: '2025-01-01T00:00:00Z' - endDate: - type: string - format: date-time - description: Campaign end date in UTC (ISO 8601 format) - example: '2025-01-31T23:59:59Z' - channels: - type: array - items: - type: string - enum: [display, video, audio, native, ctv] - description: Advertising channels (aligned with AdCP channel schema) - example: [display, video] - countries: - type: array - items: - type: string - description: ISO 3166-1 alpha-2 country codes - example: [US, CA] - objectives: - type: array - items: - type: string - description: Campaign objectives/outcomes (e.g., awareness, consideration, conversion) - example: [awareness, consideration] - brief: - type: string - description: Campaign brief text - example: Launch campaign for new product... - acceptedPricingMethods: - type: array - items: - type: string - enum: [cpm, vcpm, cpc, cpcv, cpv, cpp, flat_rate] - description: AdCP pricing models acceptable to the buyer for sales agent pricing - example: [cpm, vcpm, flat_rate] - promotedOfferings: - $ref: '#/components/schemas/PromotedOfferings' - seatId: - type: string - description: Seat/account ID for this request - example: seat_456 - - ProposedTactic: - type: object - required: - - tacticId - - execution - - budgetCapacity - - pricing - properties: - tacticId: - type: string - description: Unique identifier for this proposed tactic (you generate this) - example: premium-vcpm-display - execution: - type: string - description: How you would execute this tactic - example: Target premium inventory at $2.50 vCPM with 85% viewability - budgetCapacity: - type: number - description: Maximum budget you can effectively manage - example: 50000 - pricing: - $ref: '#/components/schemas/TacticPricing' - sku: - type: string - description: Identifier for this tactic type - example: premium-vcpm - customFieldsRequired: - type: array - items: - $ref: '#/components/schemas/CustomField' - description: Custom fields needed to execute this tactic - - GetProposedTacticsResponse: - type: object - properties: - proposedTactics: - type: array - items: - $ref: '#/components/schemas/ProposedTactic' - description: List of tactics you can handle (empty array if none) - - TacticContext: - type: object - properties: - budget: - type: number - description: Budget allocated - example: 50000 - budgetCurrency: - type: string - description: Currency for budget (ISO 4217 code) - default: USD - example: USD - startDate: - type: string - format: date-time - description: Tactic start date in UTC (ISO 8601 format) - example: '2025-01-01T00:00:00Z' - endDate: - type: string - format: date-time - description: Tactic end date in UTC (ISO 8601 format) - example: '2025-01-31T23:59:59Z' - channel: - type: string - enum: [display, video, audio, native, ctv] - description: Advertising channel (aligned with AdCP channel schema) - example: display - countries: - type: array - items: - type: string - description: Target countries - example: [US] - creatives: - type: array - items: - $ref: '#/components/schemas/Creative' - description: Creative assets to use (uses Creative from main schema) - brandStandards: - type: array - items: - $ref: '#/components/schemas/BrandStandard' - description: Brand safety and suitability requirements (uses BrandStandard from main schema) - - ManageTacticRequest: - type: object - required: - - tacticId - - tacticContext - - brandAgentId - - seatId - properties: - tacticId: - type: string - description: ID of the tactic (matches one you proposed) - example: premium-vcpm-display - tacticContext: - $ref: '#/components/schemas/TacticContext' - brandAgentId: - type: string - description: Brand agent (advertiser) for this campaign - example: ba_123 - seatId: - type: string - description: Seat/account ID - example: seat_456 - customFields: - type: object - description: Custom fields provided by advertiser - example: { targetVCPM: 2.5 } - - ManageTacticResponse: - type: object - required: - - acknowledged - properties: - acknowledged: - type: boolean - description: true to accept assignment, false to decline - example: true - reason: - type: string - description: Optional reason if declining - example: Insufficient budget for effective optimization - - PatchOperation: - type: object - properties: - op: - type: string - enum: [add, remove, replace] - description: Patch operation type - example: replace - path: - type: string - description: JSON Pointer to changed field - example: /budget - value: - description: New value for the field - - TacticContextUpdatedRequest: - type: object - required: - - tacticId - - tactic - - patch - properties: - tacticId: - type: string - description: Tactic ID - example: premium-vcpm-display - tactic: - type: object - description: Current tactic state (after changes) - patch: - type: array - items: - $ref: '#/components/schemas/PatchOperation' - description: Changes in JSON Patch format (RFC 6902) - - TacticCreativesUpdatedRequest: - type: object - required: - - tacticId - - creatives - - patch - properties: - tacticId: - type: string - description: Tactic ID - example: premium-vcpm-display - creatives: - type: array - items: - $ref: '#/components/schemas/Creative' - description: Updated creative assets - patch: - type: array - items: - $ref: '#/components/schemas/PatchOperation' - description: Changes to creatives array in JSON Patch format - - Creative: - type: object - required: - - creativeId - - name - - status - - createdAt - - updatedAt - properties: - creativeId: - type: string - description: Unique identifier for the creative - example: cr_001 - name: - type: string - description: Name of the creative - example: Summer Campaign Banner - status: - type: string - description: Status of the creative - example: ACTIVE - campaignId: - type: string - description: Campaign this creative belongs to (optional) - example: camp_123 - createdAt: - type: string - format: date-time - description: When the creative was created (ISO 8601 UTC) - example: '2025-01-01T00:00:00Z' - updatedAt: - type: string - format: date-time - description: When the creative was last updated (ISO 8601 UTC) - example: '2025-01-15T14:30:00Z' - - BrandStandard: - type: object - required: - - id - - name - - countryCodes - - channelCodes - - brands - - createdAt - - updatedAt - properties: - id: - type: string - description: Unique identifier for the brand standard - example: bs_001 - name: - type: string - description: Name of the brand standard - example: Premium Brand Safety - description: - type: string - description: Description of the standard (optional) - example: High viewability requirements for premium inventory - countryCodes: - type: array - items: - type: string - description: ISO 3166-1 alpha-2 country codes this standard applies to - example: [US, CA] - channelCodes: - type: array - items: - type: string - description: Channels this standard applies to - example: [display, video] - brands: - type: array - items: - type: string - description: Brand names this standard applies to - example: [Brand A, Brand B] - createdAt: - type: string - format: date-time - description: When the standard was created (ISO 8601 UTC) - example: '2025-01-01T00:00:00Z' - updatedAt: - type: string - format: date-time - description: When the standard was last updated (ISO 8601 UTC) - example: '2025-01-15T14:30:00Z' - - TacticFeedbackRequest: - type: object - required: - - tacticId - - startDate - - endDate - - deliveryIndex - - performanceIndex - properties: - tacticId: - type: string - description: Tactic ID - example: premium-vcpm-display - startDate: - type: string - format: date-time - description: Start of feedback interval in UTC (ISO 8601 format) - example: '2025-01-01T00:00:00Z' - endDate: - type: string - format: date-time - description: End of feedback interval in UTC (ISO 8601 format) - example: '2025-01-07T23:59:59Z' - deliveryIndex: - type: number - description: Delivery performance (100 = on target) - example: 95 - performanceIndex: - type: number - description: Performance vs target or peers (100 = maximum) - example: 110 - - PromotedOfferings: - type: object - description: Complete offering specification combining brand manifest, product selectors, and inline offerings (AdCP spec) - required: - - brand_manifest - properties: - brand_manifest: - oneOf: - - $ref: '#/components/schemas/BrandManifest' - - type: string - description: URL reference to a hosted brand manifest - example: https://brand.example.com/manifest.json - description: Brand information manifest (inline object or URL reference) - product_selectors: - type: object - description: Optional product catalog selectors - properties: - product_ids: - type: array - items: - type: string - description: Specific product IDs to promote - example: [prod_123, prod_456] - offerings: - type: array - description: Inline offerings for campaigns without a product catalog - items: - type: object - required: - - name - properties: - name: - type: string - description: Offering name - example: Winter Sale - description: - type: string - description: Description of what's being offered - example: 20% off all winter products - assets: - type: array - description: Assets specific to this offering - items: - type: object - - BrandManifest: - type: object - description: Brand information manifest containing assets, themes, and guidelines (AdCP spec) - properties: - url: - type: string - format: uri - description: Primary brand URL for context and asset discovery - example: https://brand.example.com - name: - type: string - description: Brand or business name - example: Acme Corporation - logos: - type: array - description: Brand logo assets with semantic tags - items: - type: object - required: - - url - properties: - url: - type: string - format: uri - description: URL to the logo asset - example: https://cdn.example.com/logo.png - tags: - type: array - items: - type: string - description: Semantic tags (e.g., 'dark', 'light', 'square', 'horizontal', 'icon') - example: [dark, horizontal] - width: - type: number - description: Logo width in pixels - example: 200 - height: - type: number - description: Logo height in pixels - example: 50 - colors: - type: object - description: Brand color palette - properties: - primary: - type: string - description: Primary brand color (hex) - example: '#0D9373' - secondary: - type: string - description: Secondary brand color (hex) - example: '#07C983' - accent: - type: string - description: Accent color (hex) - background: - type: string - description: Background color (hex) - text: - type: string - description: Text color (hex) - fonts: - type: object - description: Brand typography guidelines - properties: - primary: - type: string - description: Primary font family name - example: Inter - secondary: - type: string - description: Secondary font family name - example: Georgia - font_urls: - type: array - items: - type: string - format: uri - description: URLs to web font files if using custom fonts - tone: - type: string - description: Brand voice and messaging tone - example: professional - tagline: - type: string - description: Brand tagline or slogan - example: Innovation that moves you forward - product_catalog: - type: object - description: Product catalog information for e-commerce advertisers (enables SKU-level creative generation) - required: - - feed_url - properties: - feed_url: - type: string - format: uri - description: URL to product catalog feed - example: https://brand.example.com/products.xml - feed_format: - type: string - enum: [google_merchant_center, facebook_catalog, custom] - description: Format of the product feed - categories: - type: array - items: - type: string - description: Product categories available in the catalog - example: [electronics, apparel, home_goods] - last_updated: - type: string - format: date-time - description: When the product catalog was last updated - update_frequency: - type: string - enum: [realtime, hourly, daily, weekly] - description: How frequently the product catalog is updated - industry: - type: string - description: Industry or vertical - example: retail - target_audience: - type: string - description: Primary target audience description - example: Tech-savvy millennials aged 25-40 - disclaimers: - type: array - description: Legal disclaimers or required text that must appear in creatives - items: - type: object - required: - - text - properties: - text: - type: string - description: Disclaimer text - context: - type: string - description: When this disclaimer applies (e.g., financial_products, all) - required: - type: boolean - description: Whether this disclaimer must appear - contact: - type: object - description: Brand contact information - properties: - email: - type: string - format: email - description: Contact email - phone: - type: string - description: Contact phone number diff --git a/openapi.yaml b/openapi.yaml deleted file mode 100644 index afc321e..0000000 --- a/openapi.yaml +++ /dev/null @@ -1,10037 +0,0 @@ -# This OpenAPI specification is auto-generated from TypeScript Schemas -# DO NOT EDIT THIS FILE MANUALLY - -openapi: 3.0.0 -info: - title: Scope3 Agentic API - version: 1.0.0 - description: >- - Comprehensive API for the Scope3 Agentic Advertising Platform. - - This API provides tools for managing brand agents, campaigns, creatives, tactics, media buys, and more through - natural language interfaces and structured endpoints. -servers: - - url: https://api.agentic.scope3.com/mcp - description: Production server - - url: https://api.agentic.staging.scope3.com/mcp - description: Staging server -paths: - /mcp-initialize: - post: - operationId: mcp_initialize - summary: Initialize MCP session - description: >- - Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as - a UUID and included in the mcp-session-id header for all subsequent requests. - tags: - - MCP - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: MCP session identifier (UUID). Generate a new UUID for session initialization. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - jsonrpc: - type: string - enum: - - '2.0' - id: - oneOf: - - type: string - - type: number - method: - type: string - enum: - - initialize - params: - type: object - properties: - protocolVersion: - type: string - example: '2024-11-05' - capabilities: - type: object - clientInfo: - type: object - properties: - name: - type: string - version: - type: string - required: - - name - - version - required: - - protocolVersion - - capabilities - - clientInfo - required: - - jsonrpc - - id - - method - - params - responses: - '200': - description: Session initialized successfully - content: - application/json: - schema: - type: object - properties: - jsonrpc: - type: string - enum: - - '2.0' - id: - oneOf: - - type: string - - type: number - result: - type: object - properties: - protocolVersion: - type: string - capabilities: - type: object - serverInfo: - type: object - properties: - name: - type: string - version: - type: string - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - /brand-agent-list: - post: - operationId: brand_agent_list - summary: List brand agents - description: >- - List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no - parameters required. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_list - arguments: - $ref: '#/components/schemas/ListBrandAgentsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-agent-get: - post: - operationId: brand_agent_get - summary: Get brand agent - description: Get detailed information about a specific brand agent (advertiser account) by ID. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_get - arguments: - $ref: '#/components/schemas/GetBrandAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-agent-create: - post: - operationId: brand_agent_create - summary: Create brand agent - description: >- - Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, - creatives, audiences, standards, and measurement sources. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_create - arguments: - $ref: '#/components/schemas/CreateBrandAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-agent-update: - post: - operationId: brand_agent_update - summary: Update brand agent - description: Update an existing brand agent with new information. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_update - arguments: - $ref: '#/components/schemas/UpdateBrandAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-agent-delete: - post: - operationId: brand_agent_delete - summary: Delete brand agent - description: Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_delete - arguments: - $ref: '#/components/schemas/DeleteBrandAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-list: - post: - operationId: campaign_list - summary: List campaigns - description: List all campaigns with optional filtering by brand agent. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_list - arguments: - $ref: '#/components/schemas/ListCampaignsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-create: - post: - operationId: campaign_create - summary: Create campaign - description: >- - Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, - budget, and creative requirements. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_create - arguments: - $ref: '#/components/schemas/CreateCampaignInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-get: - post: - operationId: campaign_get - summary: Get campaign - description: Get detailed information about a specific campaign. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_get - arguments: - $ref: '#/components/schemas/GetCampaignInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-update: - post: - operationId: campaign_update - summary: Update campaign - description: Update an existing campaign with new information. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_update - arguments: - $ref: '#/components/schemas/UpdateCampaignInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-delete: - post: - operationId: campaign_delete - summary: Delete campaign - description: Delete a campaign and all associated resources. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_delete - arguments: - $ref: '#/components/schemas/DeleteCampaignInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-get-summary: - post: - operationId: campaign_get_summary - summary: Get campaign summary - description: Get a high-level summary of a campaign including key metrics and status. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_get_summary - arguments: - $ref: '#/components/schemas/GetCampaignSummaryInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignGetSummary' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-list-tactics: - post: - operationId: campaign_list_tactics - summary: List campaign tactics - description: List all tactics associated with a specific campaign. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_list_tactics - arguments: - $ref: '#/components/schemas/ListCampaignTacticsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignListTactics' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-validate-brief: - post: - operationId: campaign_validate_brief - summary: Validate campaign brief - description: Validate a campaign brief to ensure it contains all necessary information for campaign creation. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_validate_brief - arguments: - $ref: '#/components/schemas/ValidateBriefInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignValidateBrief' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /asset-list: - post: - operationId: asset_list - summary: List assets - description: List all uploaded assets with optional filtering by brand agent. - tags: - - Assets - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - asset_list - arguments: - $ref: '#/components/schemas/ListAssetsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AssetList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-standards-create: - post: - operationId: brand_standards_create - summary: Create brand standards - description: >- - Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand - agent. - tags: - - Brand Standards - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_standards_create - arguments: - $ref: '#/components/schemas/CreateBrandStandardInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStandardsCreateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-standards-delete: - post: - operationId: brand_standards_delete - summary: Delete brand standards - description: Delete brand standards for a brand agent. - tags: - - Brand Standards - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_standards_delete - arguments: - $ref: '#/components/schemas/DeleteBrandStandardInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStandardsDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-standards-list: - post: - operationId: brand_standards_list - summary: List brand standards - description: List all brand standards with optional filtering by brand agent. - tags: - - Brand Standards - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_standards_list - arguments: - $ref: '#/components/schemas/ListBrandStandardsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStandardsList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-story-create: - post: - operationId: brand_story_create - summary: Create brand story - description: Create a brand story containing the narrative, history, values, and key messaging for a brand agent. - tags: - - Brand Stories - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_story_create - arguments: - $ref: '#/components/schemas/CreateBrandStoryInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStoryCreate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-story-update: - post: - operationId: brand_story_update - summary: Update brand story - description: Update an existing brand story with new information. - tags: - - Brand Stories - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_story_update - arguments: - $ref: '#/components/schemas/UpdateBrandStoryInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStoryUpdate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-story-delete: - post: - operationId: brand_story_delete - summary: Delete brand story - description: Delete a brand story. - tags: - - Brand Stories - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_story_delete - arguments: - $ref: '#/components/schemas/DeleteBrandStoryInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStoryDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-story-list: - post: - operationId: brand_story_list - summary: List brand stories - description: List all brand stories with optional filtering by brand agent. - tags: - - Brand Stories - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - brand_story_list - arguments: - $ref: '#/components/schemas/ListBrandStoriesInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStoryList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /channel-list: - post: - operationId: channel_list - summary: List channels - description: List all available advertising channels and platforms. - tags: - - Channels - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - channel_list - arguments: - $ref: '#/components/schemas/ListChannelsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/ChannelList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-assign: - post: - operationId: creative_assign - summary: Assign creative - description: Assign a creative to a tactic or media buy. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - creative_assign - arguments: - $ref: '#/components/schemas/AssignCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeAssign' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-create: - post: - operationId: creative_create - summary: Create creative - description: Create a new creative with assets, copy, and targeting specifications. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - creative_create - arguments: - $ref: '#/components/schemas/CreateCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-update: - post: - operationId: creative_update - summary: Update creative - description: Update an existing creative with new assets, copy, or specifications. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - creative_update - arguments: - $ref: '#/components/schemas/UpdateCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-delete: - post: - operationId: creative_delete - summary: Delete creative - description: Delete a creative and remove it from any associated tactics or media buys. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - creative_delete - arguments: - $ref: '#/components/schemas/DeleteCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-get: - post: - operationId: creative_get - summary: Get creative - description: Get detailed information about a specific creative. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - creative_get - arguments: - $ref: '#/components/schemas/GetCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-list: - post: - operationId: creative_list - summary: List creatives - description: List all creatives with optional filtering by brand agent or campaign. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - creative_list - arguments: - $ref: '#/components/schemas/ListCreativesInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-sync-sales-agents: - post: - operationId: creative_sync_sales_agents - summary: Sync creatives to sales agents - description: Synchronize creatives to connected sales agents (DSPs, publisher platforms). - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - creative_sync_sales_agents - arguments: - $ref: '#/components/schemas/SyncSalesAgentsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeSyncSalesAgents' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-create: - post: - operationId: media_buy_create - summary: Create media buy - description: Create a new media buy with budget, targeting, and creative specifications. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_create - arguments: - $ref: '#/components/schemas/CreateMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-update: - post: - operationId: media_buy_update - summary: Update media buy - description: Update an existing media buy with new budget, targeting, or creative assignments. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_update - arguments: - $ref: '#/components/schemas/UpdateMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-delete: - post: - operationId: media_buy_delete - summary: Delete media buy - description: Delete a media buy and cancel any active placements. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_delete - arguments: - $ref: '#/components/schemas/DeleteMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-execute: - post: - operationId: media_buy_execute - summary: Execute media buy - description: Execute a media buy, sending it to the configured sales agents for placement. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_execute - arguments: - $ref: '#/components/schemas/ExecuteMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyExecute' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-get: - post: - operationId: media_buy_get - summary: Get media buy - description: Get detailed information about a specific media buy. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_get - arguments: - $ref: '#/components/schemas/GetMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-list: - post: - operationId: media_buy_list - summary: List media buys - description: List all media buys with optional filtering by brand agent, campaign, or status. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_list - arguments: - $ref: '#/components/schemas/ListMediaBuysInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-validate-budget: - post: - operationId: media_buy_validate_budget - summary: Validate media buy budget - description: Validate a media buy budget against campaign constraints and available funds. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_validate_budget - arguments: - $ref: '#/components/schemas/ValidateMediaBuyBudgetInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyValidateBudget' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /notifications-list: - post: - operationId: notifications_list - summary: List notifications - description: List notifications for the authenticated user with optional filtering by status. - tags: - - Notifications - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - notifications_list - arguments: - $ref: '#/components/schemas/ListNotificationsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/NotificationsList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /notifications-mark-read: - post: - operationId: notifications_mark_read - summary: Mark notification as read - description: Mark a specific notification as read. - tags: - - Notifications - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - notifications_mark_read - arguments: - $ref: '#/components/schemas/MarkNotificationReadInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/NotificationsMarkRead' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /notifications-mark-acknowledged: - post: - operationId: notifications_mark_acknowledged - summary: Mark notification as acknowledged - description: Mark a specific notification as acknowledged. - tags: - - Notifications - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - notifications_mark_acknowledged - arguments: - $ref: '#/components/schemas/MarkNotificationAcknowledgedInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/NotificationsMarkAcknowledged' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /notifications-mark-all-read: - post: - operationId: notifications_mark_all_read - summary: Mark all notifications as read - description: Mark all notifications for the authenticated user as read. - tags: - - Notifications - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - notifications_mark_all_read - arguments: - $ref: '#/components/schemas/MarkAllNotificationsReadInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/NotificationsMarkAllRead' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-product-discover: - post: - operationId: media_product_discover - summary: Discover media products - description: Discover available media products from connected sales agents based on targeting criteria. - tags: - - Media Products - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_product_discover - arguments: - $ref: '#/components/schemas/DiscoverProductsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaProductDiscover' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-product-save: - post: - operationId: media_product_save - summary: Save media product - description: Save a discovered media product for future use in media buys. - tags: - - Media Products - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_product_save - arguments: - $ref: '#/components/schemas/SaveProductInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaProductSave' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-product-list: - post: - operationId: media_product_list - summary: List media products - description: List saved media products with optional filtering. - tags: - - Media Products - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_product_list - arguments: - $ref: '#/components/schemas/ListProductsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaProductList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-product-sync: - post: - operationId: media_product_sync - summary: Sync media products - description: Synchronize media product catalog from connected sales agents. - tags: - - Media Products - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - media_product_sync - arguments: - $ref: '#/components/schemas/SyncProductsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaProductSync' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-get: - post: - operationId: agent_get - summary: Get agent - description: >- - Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the - agent ID. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - agent_get - arguments: - $ref: '#/components/schemas/GetAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentGet' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-list: - post: - operationId: agent_list - summary: List agents - description: >- - List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, - organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - agent_list - arguments: - $ref: '#/components/schemas/ListAgentsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-register: - post: - operationId: agent_register - summary: Register agent - description: Register a new agent for media buying (SALES type) or outcome optimization (OUTCOME type). - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - agent_register - arguments: - $ref: '#/components/schemas/RegisterAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentRegister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-unregister: - post: - operationId: agent_unregister - summary: Unregister agent - description: Unregister an agent and disconnect it from the platform. Type is automatically inferred from the agent ID. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - agent_unregister - arguments: - $ref: '#/components/schemas/UnregisterAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentUnregister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-update: - post: - operationId: agent_update - summary: Update agent - description: Update agent configuration and credentials. Type is automatically inferred from the agent ID. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - agent_update - arguments: - $ref: '#/components/schemas/UpdateAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentUpdate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /sales-agent-get: - post: - operationId: sales_agent_get - summary: Get sales agent (DEPRECATED) - description: >- - DEPRECATED: Use agent_get instead. Get detailed information about a specific sales agent (DSP, publisher - platform). - tags: - - Sales Agents (Deprecated) - deprecated: true - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - sales_agent_get - arguments: - $ref: '#/components/schemas/GetSalesAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/SalesAgentGet' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /sales-agent-list: - post: - operationId: sales_agent_list - summary: List sales agents (DEPRECATED) - description: 'DEPRECATED: Use agent_list instead. List all registered sales agents (DSPs, publisher platforms).' - tags: - - Sales Agents (Deprecated) - deprecated: true - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - sales_agent_list - arguments: - $ref: '#/components/schemas/ListSalesAgentsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/SalesAgentList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /sales-agent-register: - post: - operationId: sales_agent_register - summary: Register sales agent (DEPRECATED) - description: 'DEPRECATED: Use agent_register instead. Register a new sales agent (DSP, publisher platform) for media buying.' - tags: - - Sales Agents (Deprecated) - deprecated: true - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - sales_agent_register - arguments: - $ref: '#/components/schemas/RegisterSalesAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/SalesAgentRegister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /sales-agent-unregister: - post: - operationId: sales_agent_unregister - summary: Unregister sales agent (DEPRECATED) - description: 'DEPRECATED: Use agent_unregister instead. Unregister a sales agent and disconnect it from the platform.' - tags: - - Sales Agents (Deprecated) - deprecated: true - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - sales_agent_unregister - arguments: - $ref: '#/components/schemas/UnregisterSalesAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/SalesAgentUnregister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /sales-agent-update: - post: - operationId: sales_agent_update - summary: Update sales agent (DEPRECATED) - description: 'DEPRECATED: Use agent_update instead. Update sales agent configuration and credentials.' - tags: - - Sales Agents (Deprecated) - deprecated: true - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - sales_agent_update - arguments: - $ref: '#/components/schemas/UpdateSalesAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/SalesAgentUpdate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /sales-agent-account-list: - post: - operationId: sales_agent_account_list - summary: List sales agent accounts - description: List all accounts (seats, advertisers) within a sales agent. - tags: - - Sales Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - sales_agent_account_list - arguments: - $ref: '#/components/schemas/ListSalesAgentAccountsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/SalesAgentAccountList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /sales-agent-account-register: - post: - operationId: sales_agent_account_register - summary: Register sales agent account - description: Register a new account (seat, advertiser) within a sales agent. - tags: - - Sales Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - sales_agent_account_register - arguments: - $ref: '#/components/schemas/RegisterSalesAgentAccountInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/SalesAgentAccountRegister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /sales-agent-account-unregister: - post: - operationId: sales_agent_account_unregister - summary: Unregister sales agent account - description: Unregister an account from a sales agent. - tags: - - Sales Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - sales_agent_account_unregister - arguments: - $ref: '#/components/schemas/UnregisterSalesAgentAccountInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/SalesAgentAccountUnregister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /sales-agent-account-update: - post: - operationId: sales_agent_account_update - summary: Update sales agent account - description: Update account configuration within a sales agent. - tags: - - Sales Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - sales_agent_account_update - arguments: - $ref: '#/components/schemas/UpdateSalesAgentAccountInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/SalesAgentAccountUpdate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-create: - post: - operationId: tactic_create - summary: Create tactic - description: Create a new tactic defining how to achieve campaign objectives. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_create - arguments: - $ref: '#/components/schemas/CreateTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticCreate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-update: - post: - operationId: tactic_update - summary: Update tactic - description: Update an existing tactic with new targeting, budget, or creative requirements. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_update - arguments: - $ref: '#/components/schemas/UpdateTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-delete: - post: - operationId: tactic_delete - summary: Delete tactic - description: Delete a tactic and all associated media buys. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_delete - arguments: - $ref: '#/components/schemas/DeleteTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-get: - post: - operationId: tactic_get - summary: Get tactic - description: Get detailed information about a specific tactic. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_get - arguments: - $ref: '#/components/schemas/GetTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-list: - post: - operationId: tactic_list - summary: List tactics - description: List all tactics with optional filtering by brand agent or campaign. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_list - arguments: - $ref: '#/components/schemas/ListTacticsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-link-campaign: - post: - operationId: tactic_link_campaign - summary: Link tactic to campaign - description: Link a tactic to a campaign. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_link_campaign - arguments: - $ref: '#/components/schemas/LinkCampaignToTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticLinkCampaign' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-unlink-campaign: - post: - operationId: tactic_unlink_campaign - summary: Unlink tactic from campaign - description: Unlink a tactic from a campaign. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_unlink_campaign - arguments: - $ref: '#/components/schemas/UnlinkCampaignFromTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticUnlinkCampaign' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /webhook-register: - post: - operationId: webhook_register - summary: Register webhook - description: Register a webhook to receive real-time notifications about events. - tags: - - Webhooks - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - webhook_register - arguments: - $ref: '#/components/schemas/RegisterWebhookInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/WebhookRegister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /webhook-list: - post: - operationId: webhook_list - summary: List webhooks - description: List all registered webhooks. - tags: - - Webhooks - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - webhook_list - arguments: - $ref: '#/components/schemas/ListWebhooksInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/WebhookList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /webhook-delete: - post: - operationId: webhook_delete - summary: Delete webhook - description: Delete a registered webhook. - tags: - - Webhooks - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - tool: - type: string - enum: - - webhook_delete - arguments: - $ref: '#/components/schemas/DeleteWebhookInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/WebhookDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' -components: - schemas: - ListAssetsInput: - type: object - properties: - brandAgentId: - description: Optional brand agent ID to filter assets - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - ListBrandAgentsInput: - description: Parameters for listing brand agents. Authentication is automatic. - type: object - properties: - where: - description: Prisma-style where clause for filtering agents - type: object - additionalProperties: {} - orderBy: - description: Prisma-style orderBy clause - type: object - additionalProperties: {} - take: - description: Number of records to return - example: 10 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - skip: - description: Number of records to skip - example: 0 - type: integer - minimum: 0 - maximum: 9007199254740991 - distinct: - description: Fields to use for distinct selection - type: array - items: - type: string - GetBrandAgentInput: - description: Parameters for retrieving a specific brand agent - type: object - properties: - brandAgentId: - description: The unique identifier for the brand agent - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - required: - - brandAgentId - CreateBrandAgentInput: - description: Parameters for creating a new brand agent - type: object - properties: - name: - description: Name of the brand agent (advertiser account) - example: Nike Global Campaigns - type: string - minLength: 1 - maxLength: 255 - description: - description: Optional description of the brand agent - example: Brand agent for Nike global advertising campaigns - type: string - maxLength: 1000 - manifestUrl: - description: URL to the brand manifest - example: https://example.com/brand-manifest - type: string - format: uri - countryCodes: - description: Country codes (ISO 3166-1 alpha-2) - example: - - US - - CA - - GB - type: array - items: - type: string - minLength: 2 - maxLength: 2 - required: - - name - UpdateBrandAgentInput: - description: Parameters for updating a brand agent - type: object - properties: - brandAgentId: - description: The unique identifier for the brand agent - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - name: - description: Updated name of the brand agent - type: string - minLength: 1 - maxLength: 255 - description: - description: Updated description - type: string - maxLength: 1000 - manifestUrl: - description: Updated URL to the brand manifest - example: https://example.com/brand-manifest - type: string - format: uri - countryCodes: - description: Updated country codes - type: array - items: - type: string - minLength: 2 - maxLength: 2 - required: - - brandAgentId - DeleteBrandAgentInput: - description: Parameters for deleting a brand agent - type: object - properties: - brandAgentId: - description: The unique identifier for the brand agent to delete - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - required: - - brandAgentId - CreateBrandStandardInput: - type: object - properties: - brandAgentId: - description: Brand agent ID - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - name: - description: Standard name - type: string - minLength: 1 - maxLength: 255 - description: - description: Standard description - type: string - prompt: - description: Brand standards prompt - type: string - minLength: 1 - isPrimary: - description: Whether this is the primary standard - type: boolean - countries: - description: Country codes - type: array - items: - type: string - channels: - description: Channel types - type: array - items: - type: string - enum: - - ctv - - video - - display - - app - - social - brands: - description: Brand names - type: array - items: - type: string - required: - - brandAgentId - - prompt - DeleteBrandStandardInput: - type: object - properties: - brandStandardId: - description: Brand standard ID - type: string - required: - - brandStandardId - ListBrandStandardsInput: - type: object - properties: - brandAgentId: - description: Optional brand agent ID to filter brand standards by - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - where: - description: Prisma-style where clause for filtering standards - type: object - additionalProperties: {} - orderBy: - description: Prisma-style orderBy clause - type: object - additionalProperties: {} - take: - description: Number of records to return - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - skip: - description: Number of records to skip - type: integer - minimum: 0 - maximum: 9007199254740991 - distinct: - description: Fields to use for distinct selection - type: array - items: - type: string - CreateBrandStoryInput: - type: object - properties: - brandAgentId: - description: Brand agent ID (bigint or string) - anyOf: - - type: integer - format: int64 - - type: string - name: - description: Story name - type: string - minLength: 1 - maxLength: 255 - prompt: - description: Brand story prompt - type: string - brands: - description: Brand names - type: array - items: - type: string - languages: - description: Language codes (use language_list tool to see available options) - type: array - items: - type: string - required: - - brandAgentId - - name - - languages - UpdateBrandStoryInput: - type: object - properties: - brandStoryId: - description: Brand story ID - type: string - name: - description: Story name - type: string - prompt: - description: Updated brand story prompt - type: string - minLength: 1 - required: - - brandStoryId - - prompt - DeleteBrandStoryInput: - type: object - properties: - brandStoryId: - description: Brand story ID - type: string - required: - - brandStoryId - ListBrandStoriesInput: - type: object - properties: - brandAgentId: - description: Optional brand agent ID to filter brand stories by - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - where: - description: Filtering criteria - type: object - additionalProperties: {} - orderBy: - description: Ordering criteria - type: object - additionalProperties: {} - take: - description: Number of records to return - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - skip: - description: Number of records to skip - type: integer - minimum: 0 - maximum: 9007199254740991 - distinct: - description: Fields to use for distinct selection - type: array - items: - type: string - ListCampaignsInput: - description: Parameters for listing campaigns - type: object - properties: - brandAgentId: - description: Filter by brand agent ID - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - status: - description: Filter by campaign status - type: string - enum: - - ACTIVE - - PAUSED - - ARCHIVED - - DRAFT - limit: - description: Number of results to return - example: 50 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - offset: - description: Number of results to skip for pagination - example: 0 - type: integer - minimum: 0 - maximum: 9007199254740991 - CreateCampaignInput: - description: Parameters for creating a new campaign - type: object - properties: - brandAgentId: - description: Brand agent ID that will own this campaign - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - name: - description: Optional name for the campaign (auto-generated if not provided) - example: Summer 2025 Tech Campaign - type: string - minLength: 1 - maxLength: 255 - prompt: - description: >- - Natural language description of campaign requirements. The backend will parse this to extract targeting, - budget, and creative requirements. - example: Create a video campaign targeting tech enthusiasts aged 25-45 with $50k budget - type: string - minLength: 10 - budget: - description: Budget configuration for the campaign - type: object - properties: - total: - type: number - minimum: 0 - exclusiveMinimum: true - currency: - default: USD - type: string - minLength: 3 - maxLength: 3 - dailyCap: - type: number - minimum: 0 - exclusiveMinimum: true - pacing: - type: string - enum: - - EVEN - - ASAP - - FRONTLOADED - required: - - total - startDate: - description: Campaign start date (ISO 8601 format) - example: '2025-01-15T00:00:00Z' - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - endDate: - description: Campaign end date (ISO 8601 format) - example: '2025-03-31T23:59:59Z' - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - scoringWeights: - description: Scoring weights for campaign optimization - type: object - properties: - affinity: - type: number - minimum: 0 - maximum: 1 - outcome: - type: number - minimum: 0 - maximum: 1 - quality: - type: number - minimum: 0 - maximum: 1 - outcomeScoreWindowDays: - description: Number of days for outcome measurement window - example: 30 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - status: - description: Initial campaign status - type: string - enum: - - ACTIVE - - PAUSED - - ARCHIVED - - DRAFT - required: - - brandAgentId - - prompt - GetCampaignInput: - description: Parameters for retrieving a specific campaign - type: object - properties: - campaignId: - description: The unique identifier for the campaign - example: cmp_987654321 - type: string - minLength: 1 - required: - - campaignId - UpdateCampaignInput: - description: Parameters for updating a campaign - type: object - properties: - campaignId: - description: The unique identifier for the campaign - example: cmp_987654321 - type: string - minLength: 1 - name: - description: Updated campaign name - type: string - minLength: 1 - maxLength: 255 - prompt: - description: Updated campaign prompt - type: string - minLength: 10 - budget: - description: Updated budget configuration - type: object - properties: - total: - type: number - minimum: 0 - exclusiveMinimum: true - currency: - default: USD - type: string - minLength: 3 - maxLength: 3 - dailyCap: - type: number - minimum: 0 - exclusiveMinimum: true - pacing: - type: string - enum: - - EVEN - - ASAP - - FRONTLOADED - startDate: - description: Updated start date - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - endDate: - description: Updated end date - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - scoringWeights: - description: Updated scoring weights - type: object - properties: - affinity: - type: number - minimum: 0 - maximum: 1 - outcome: - type: number - minimum: 0 - maximum: 1 - quality: - type: number - minimum: 0 - maximum: 1 - outcomeScoreWindowDays: - description: Updated outcome score window days - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - status: - description: Updated campaign status - type: string - enum: - - ACTIVE - - PAUSED - - ARCHIVED - - DRAFT - required: - - campaignId - DeleteCampaignInput: - description: Parameters for deleting a campaign - type: object - properties: - campaignId: - description: The unique identifier for the campaign to delete - example: cmp_987654321 - type: string - minLength: 1 - hardDelete: - description: 'If true, permanently delete the campaign. Default: false (soft delete/archive)' - type: boolean - required: - - campaignId - GetCampaignSummaryInput: - type: object - properties: - campaignId: - description: Campaign ID - type: string - required: - - campaignId - ListCampaignTacticsInput: - type: object - properties: - campaignId: - description: Campaign ID - type: string - required: - - campaignId - ValidateBriefInput: - type: object - properties: - brief: - description: Campaign brief text - type: string - minLength: 10 - required: - - brief - ListChannelsInput: - type: object - properties: {} - AssignCreativeInput: - type: object - properties: - creativeId: - type: string - campaignId: - type: string - required: - - creativeId - - campaignId - CreateCreativeInput: - type: object - properties: - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - organizationId: - type: string - name: - type: string - minLength: 1 - maxLength: 255 - description: - type: string - formatSource: - type: string - enum: - - ADCP - - CREATIVE_AGENT - - PUBLISHER - formatId: - description: >- - Format identifier. For ADCP sources, this should be a format ID string recognized by the target sales agent - (e.g., display_300x250, video_1920x1080). Valid formats are agent-specific. - type: string - mediaUrl: - type: string - assets: - description: >- - Optional: Upload assets inline with the creative. Each asset requires: name, contentType, data (base64), and - assetType. - type: array - items: - type: object - properties: - name: - description: Filename (e.g., banner.png) - type: string - contentType: - description: MIME type (e.g., image/png, image/jpeg) - type: string - data: - description: Base64-encoded file data (without data:image/png;base64, prefix) - format: byte - type: string - assetType: - description: Type of asset - type: string - enum: - - image - - video - - audio - - logo - - font - tags: - description: Optional tags - type: array - items: - type: string - required: - - name - - contentType - - data - - assetType - content: - type: object - additionalProperties: {} - assemblyMethod: - type: string - enum: - - CREATIVE_AGENT - - ACTIVATION - - PUBLISHER - campaignId: - description: Optional campaign ID (object ID) to assign creative to - type: string - required: - - brandAgentId - - name - UpdateCreativeInput: - type: object - properties: - creativeId: - type: string - name: - type: string - status: - type: string - required: - - creativeId - DeleteCreativeInput: - type: object - properties: - creativeId: - type: string - required: - - creativeId - GetCreativeInput: - type: object - properties: - creativeId: - type: string - required: - - creativeId - ListCreativesInput: - type: object - properties: - campaignId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - formatSource: - type: string - enum: - - ADCP - - CREATIVE_AGENT - - PUBLISHER - status: - type: string - enum: - - ACTIVE - - PAUSED - - ARCHIVED - - DRAFT - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - SyncSalesAgentsInput: - type: object - properties: - creativeId: - type: string - required: - - creativeId - CreateMediaBuyInput: - type: object - properties: - tacticId: - type: number - agentId: - type: string - name: - type: string - minLength: 1 - description: - type: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - budgetAmount: - type: number - minimum: 0 - exclusiveMinimum: true - budgetCurrency: - type: string - pricingCpm: - type: number - minimum: 0 - exclusiveMinimum: true - pricingSignalCost: - type: number - displayOrder: - type: integer - minimum: -9007199254740991 - maximum: 9007199254740991 - creatives: - type: array - items: - type: object - properties: - creative_id: - type: string - name: - type: string - format_id: - anyOf: - - type: string - - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - assets: - type: object - additionalProperties: - type: object - properties: - url: - type: string - width: - type: number - height: - type: number - required: - - url - click_url: - type: string - required: - - creative_id - - name - - format_id - required: - - mediaProductId - - budgetAmount - creatives: - type: array - items: - type: object - properties: - creative_id: - type: string - name: - type: string - format_id: - anyOf: - - type: string - - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - assets: - type: object - additionalProperties: - type: object - properties: - url: - type: string - width: - type: number - height: - type: number - required: - - url - click_url: - type: string - required: - - creative_id - - name - - format_id - required: - - tacticId - - agentId - - name - - products - UpdateMediaBuyInput: - type: object - properties: - mediaBuyId: - type: string - name: - type: string - description: - type: string - status: - type: string - enum: - - DRAFT - - PENDING_APPROVAL - - ACTIVE - - PAUSED - - COMPLETED - - FAILED - - REJECTED - creativeIds: - type: array - items: - type: string - packages: - type: array - items: - type: object - properties: - packageId: - type: string - creativeIds: - type: array - items: - type: string - required: - - packageId - - creativeIds - required: - - mediaBuyId - DeleteMediaBuyInput: - type: object - properties: - mediaBuyId: - type: string - confirm: - type: boolean - required: - - mediaBuyId - - confirm - ExecuteMediaBuyInput: - type: object - properties: - mediaBuyId: - type: string - required: - - mediaBuyId - GetMediaBuyInput: - type: object - properties: - mediaBuyId: - type: string - required: - - mediaBuyId - ListMediaBuysInput: - type: object - properties: - tacticId: - type: number - status: - type: string - enum: - - DRAFT - - PENDING_APPROVAL - - ACTIVE - - PAUSED - - COMPLETED - - FAILED - - REJECTED - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - ValidateMediaBuyBudgetInput: - type: object - properties: - tacticId: - type: number - newBudgetAmount: - type: number - minimum: 0 - exclusiveMinimum: true - required: - - tacticId - - newBudgetAmount - ListNotificationsInput: - type: object - properties: - brandAgentId: - type: number - campaignId: - type: string - creativeId: - type: string - tacticId: - type: string - types: - type: array - items: - type: string - unreadOnly: - type: boolean - limit: - type: number - offset: - type: number - MarkNotificationReadInput: - type: object - properties: - notificationId: - type: string - required: - - notificationId - MarkNotificationAcknowledgedInput: - type: object - properties: - notificationId: - type: string - required: - - notificationId - MarkAllNotificationsReadInput: - type: object - properties: {} - DiscoverProductsInput: - type: object - properties: - campaignBrief: - type: string - brandManifestUrl: - type: string - deliveryType: - type: string - enum: - - guaranteed - - non_guaranteed - formats: - type: array - items: - type: string - enum: - - audio - - display - - html5 - - native - - video - inventoryType: - type: string - enum: - - premium - - run_of_site - - targeted_package - maxCpm: - type: number - minimum: 0 - exclusiveMinimum: true - minCpm: - type: number - minimum: 0 - exclusiveMinimum: true - publisherIds: - type: array - items: - type: string - agentId: - type: string - SaveProductInput: - type: object - properties: - productId: - type: string - name: - type: string - description: - type: string - publisherId: - type: string - publisherName: - type: string - deliveryType: - type: string - enum: - - guaranteed - - non_guaranteed - inventoryType: - type: string - enum: - - premium - - run_of_site - - targeted_package - creativeFormats: - anyOf: - - type: array - items: - type: string - - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - pricingModel: - type: string - enum: - - auction - - fixed_cpm - fixedCpm: - type: number - minimum: 0 - exclusiveMinimum: true - floorCpm: - type: number - minimum: 0 - exclusiveMinimum: true - targetCpm: - type: number - minimum: 0 - exclusiveMinimum: true - pricingOptions: - type: array - items: - type: object - additionalProperties: {} - supportedTargeting: - type: array - items: - type: string - adcpAgentId: - type: string - required: - - productId - - name - - description - - publisherId - - publisherName - - deliveryType - - inventoryType - - pricingModel - ListProductsInput: - type: object - properties: - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - SyncProductsInput: - type: object - properties: - sourceId: - type: string - required: - - sourceId - GetAgentInput: - type: object - properties: - agentId: - description: The agent ID to retrieve - type: string - required: - - agentId - ListAgentsInput: - type: object - properties: - type: - description: Filter by agent type (SALES or OUTCOME) - type: string - enum: - - SALES - - OUTCOME - status: - description: Filter by status (PENDING, ACTIVE, DISABLED) - type: string - enum: - - PENDING - - ACTIVE - - DISABLED - organizationId: - description: Filter by organization ID - type: string - relationship: - description: >- - Filter by relationship (SELF = owned by you, SCOPE3 = Scope3-provided, MARKETPLACE = third-party marketplace - agents) - type: string - enum: - - SELF - - SCOPE3 - - MARKETPLACE - name: - description: Filter by agent name (partial match) - type: string - RegisterAgentInput: - type: object - properties: - type: - description: The type of agent to register - type: string - enum: - - SALES - - OUTCOME - name: - description: Agent name - type: string - minLength: 1 - description: - description: Agent description - type: string - endpointUrl: - description: Agent endpoint URL - type: string - format: uri - protocol: - description: Protocol used by the agent (MCP or A2A) - type: string - enum: - - MCP - - A2A - authenticationType: - description: Authentication type - type: string - enum: - - API_KEY - - OAUTH - - NO_AUTH - - JWT - organizationId: - description: Organization ID - type: string - authConfig: - description: Authentication configuration object - anyOf: - - type: object - properties: - type: - type: string - enum: - - jwt - privateKey: - type: string - minLength: 1 - issuer: - type: string - minLength: 1 - subject: - type: string - minLength: 1 - keyId: - type: string - minLength: 1 - scope: - type: string - minLength: 1 - tokenEndpointUrl: - type: string - format: uri - audienceUrl: - type: string - format: uri - algorithm: - type: string - enum: - - ES256 - - RS256 - environment: - type: string - required: - - type - - privateKey - - issuer - - subject - - keyId - - scope - - tokenEndpointUrl - - audienceUrl - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - bearer - - apikey - - api_key - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - oauth - - oauth2 - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: {} - required: - - type - - name - - endpointUrl - - protocol - UnregisterAgentInput: - type: object - properties: - agentId: - description: The agent ID to unregister - type: string - required: - - agentId - UpdateAgentInput: - type: object - properties: - agentId: - description: The agent ID to update - type: string - name: - description: New agent name - type: string - description: - description: New agent description - type: string - endpointUrl: - description: New endpoint URL - type: string - format: uri - protocol: - description: New protocol - type: string - enum: - - MCP - - A2A - authenticationType: - description: New authentication type - type: string - enum: - - API_KEY - - OAUTH - - NO_AUTH - - JWT - authConfig: - description: New authentication configuration - anyOf: - - type: object - properties: - type: - type: string - enum: - - jwt - privateKey: - type: string - minLength: 1 - issuer: - type: string - minLength: 1 - subject: - type: string - minLength: 1 - keyId: - type: string - minLength: 1 - scope: - type: string - minLength: 1 - tokenEndpointUrl: - type: string - format: uri - audienceUrl: - type: string - format: uri - algorithm: - type: string - enum: - - ES256 - - RS256 - environment: - type: string - required: - - type - - privateKey - - issuer - - subject - - keyId - - scope - - tokenEndpointUrl - - audienceUrl - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - bearer - - apikey - - api_key - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - oauth - - oauth2 - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: {} - required: - - agentId - GetSalesAgentInput: - type: object - properties: - agentId: - type: string - required: - - agentId - ListSalesAgentsInput: - type: object - properties: {} - RegisterSalesAgentInput: - type: object - properties: - name: - type: string - minLength: 1 - description: - type: string - endpointUrl: - type: string - format: uri - protocol: - type: string - enum: - - MCP - - A2A - authenticationType: - type: string - enum: - - API_KEY - - OAUTH - - NO_AUTH - - JWT - organizationId: - type: string - authConfig: - anyOf: - - type: object - properties: - type: - type: string - enum: - - jwt - privateKey: - type: string - minLength: 1 - issuer: - type: string - minLength: 1 - subject: - type: string - minLength: 1 - keyId: - type: string - minLength: 1 - scope: - type: string - minLength: 1 - tokenEndpointUrl: - type: string - format: uri - audienceUrl: - type: string - format: uri - algorithm: - type: string - enum: - - ES256 - - RS256 - environment: - type: string - required: - - type - - privateKey - - issuer - - subject - - keyId - - scope - - tokenEndpointUrl - - audienceUrl - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - bearer - - apikey - - api_key - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - oauth - - oauth2 - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: {} - required: - - name - - endpointUrl - - protocol - UnregisterSalesAgentInput: - type: object - properties: - agentId: - type: string - required: - - agentId - UpdateSalesAgentInput: - type: object - properties: - agentId: - type: string - name: - type: string - description: - type: string - endpointUrl: - type: string - format: uri - protocol: - type: string - enum: - - MCP - - A2A - authenticationType: - type: string - enum: - - API_KEY - - OAUTH - - NO_AUTH - - JWT - authConfig: - anyOf: - - type: object - properties: - type: - type: string - enum: - - jwt - privateKey: - type: string - minLength: 1 - issuer: - type: string - minLength: 1 - subject: - type: string - minLength: 1 - keyId: - type: string - minLength: 1 - scope: - type: string - minLength: 1 - tokenEndpointUrl: - type: string - format: uri - audienceUrl: - type: string - format: uri - algorithm: - type: string - enum: - - ES256 - - RS256 - environment: - type: string - required: - - type - - privateKey - - issuer - - subject - - keyId - - scope - - tokenEndpointUrl - - audienceUrl - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - bearer - - apikey - - api_key - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - oauth - - oauth2 - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: {} - required: - - agentId - ListSalesAgentAccountsInput: - type: object - properties: - agentId: - type: string - required: - - agentId - RegisterSalesAgentAccountInput: - type: object - properties: - agentId: - type: string - accountIdentifier: - type: string - authConfig: - anyOf: - - type: object - properties: - type: - type: string - enum: - - jwt - privateKey: - type: string - minLength: 1 - issuer: - type: string - minLength: 1 - subject: - type: string - minLength: 1 - keyId: - type: string - minLength: 1 - scope: - type: string - minLength: 1 - tokenEndpointUrl: - type: string - format: uri - audienceUrl: - type: string - format: uri - algorithm: - type: string - enum: - - ES256 - - RS256 - environment: - type: string - required: - - type - - privateKey - - issuer - - subject - - keyId - - scope - - tokenEndpointUrl - - audienceUrl - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - bearer - - apikey - - api_key - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: - auth: - type: object - properties: - type: - type: string - enum: - - oauth - - oauth2 - token: - type: string - minLength: 1 - required: - - type - - token - required: - - auth - - type: object - properties: {} - required: - - agentId - - accountIdentifier - UnregisterSalesAgentAccountInput: - type: object - properties: - accountId: - type: string - required: - - accountId - UpdateSalesAgentAccountInput: - type: object - properties: - accountId: - type: string - accountData: - type: object - additionalProperties: {} - required: - - accountId - - accountData - CreateTacticInput: - type: object - properties: - campaignId: - type: string - name: - type: string - minLength: 1 - prompt: - type: string - channelCodes: - type: array - items: - type: string - enum: - - ctv - - video - - display - - app - - social - countryCodes: - type: array - items: - type: string - languages: - description: Language codes - type: array - items: - type: string - availableBrandStandards: - type: array - items: - type: object - properties: - id: - type: number - name: - type: string - required: - - id - - name - availableBrandStory: - type: array - items: - type: object - properties: - id: - type: number - name: - type: string - required: - - id - - name - required: - - campaignId - - name - UpdateTacticInput: - type: object - properties: - tacticId: - type: number - name: - type: string - prompt: - type: string - channelCodes: - type: array - items: - type: string - enum: - - ctv - - video - - display - - app - - social - countryCodes: - type: array - items: - type: string - availableBrandStandards: - type: array - items: - type: object - properties: - id: - type: number - name: - type: string - required: - - id - - name - availableBrandStory: - type: array - items: - type: object - properties: - id: - type: number - name: - type: string - required: - - id - - name - required: - - tacticId - DeleteTacticInput: - type: object - properties: - tacticId: - type: number - confirm: - type: boolean - required: - - tacticId - - confirm - GetTacticInput: - type: object - properties: - tacticId: - type: number - required: - - tacticId - ListTacticsInput: - type: object - properties: - campaignId: - type: string - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - LinkCampaignToTacticInput: - type: object - properties: - tacticId: - type: number - campaignId: - type: string - required: - - tacticId - - campaignId - UnlinkCampaignFromTacticInput: - type: object - properties: - tacticId: - type: number - campaignId: - type: string - required: - - tacticId - - campaignId - RegisterWebhookInput: - type: object - properties: - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - endpoint: - type: object - properties: - url: - type: string - format: uri - method: - type: string - enum: - - POST - - PUT - headers: - type: object - additionalProperties: - type: string - authentication: - type: object - properties: - type: - type: string - enum: - - bearer - - basic - - hmac - credentials: - type: string - required: - - type - - credentials - required: - - url - - method - eventTypes: - type: array - items: - type: string - filters: - type: object - properties: - campaigns: - type: array - items: - type: string - tactics: - type: array - items: - type: string - creatives: - type: array - items: - type: string - mediaBuys: - type: array - items: - type: string - metrics: - type: array - items: - type: string - minSeverity: - type: string - enum: - - info - - warning - - critical - retryPolicy: - type: object - properties: - maxRetries: - type: integer - minimum: 0 - maximum: 9007199254740991 - backoffMultiplier: - type: number - minimum: 0 - exclusiveMinimum: true - maxBackoffSeconds: - type: number - minimum: 0 - exclusiveMinimum: true - required: - - endpoint - - eventTypes - ListWebhooksInput: - type: object - properties: - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - DeleteWebhookInput: - type: object - properties: - webhookId: - type: string - required: - - webhookId - BrandAgentUpdate: - type: object - properties: - id: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - name: - type: string - description: - type: string - manifestUrl: - type: string - format: uri - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - customerId - - createdAt - - updatedAt - BrandStandardsCreate: - type: object - properties: - id: - type: string - name: - type: string - description: - type: string - countryCodes: - type: array - items: - type: string - channelCodes: - type: array - items: - type: string - brands: - type: array - items: - type: string - models: - type: array - items: - type: object - properties: - id: - type: string - name: - type: string - prompt: - type: string - status: - nullable: true - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - prompt - - status - - createdAt - - updatedAt - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - countryCodes - - channelCodes - - brands - - models - - createdAt - - updatedAt - CampaignUpdate: - type: object - properties: - campaignId: - type: string - name: - type: string - status: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - campaignId - - name - - status - - createdAt - - updatedAt - CreativeGet: - type: object - properties: - creativeId: - type: string - name: - type: string - status: - type: string - campaignId: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - creativeId - - name - - status - - createdAt - - updatedAt - MediaBuyGet: - type: object - properties: - id: - type: string - tacticId: - type: number - customerId: - type: number - name: - type: string - description: - type: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - required: - - mediaProductId - - salesAgentId - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - status: - type: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - TacticGet: - type: object - properties: - id: - type: number - name: - type: string - prompt: - type: string - campaignIds: - type: array - items: - type: string - channelCodes: - type: array - items: - type: string - countryCodes: - type: array - items: - type: string - mediaBuyCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - channelCodes - - countryCodes - - createdAt - - updatedAt - MCPContent: - type: object - properties: - type: - type: string - enum: - - text - text: - type: string - required: - - type - - text - additionalProperties: false - BadRequest: - description: Bad request error response - type: object - properties: - error: - type: string - message: - type: string - required: - - error - additionalProperties: false - Unauthorized: - description: Unauthorized error response - type: object - properties: - error: - type: string - message: - type: string - required: - - error - additionalProperties: false - InternalError: - description: Internal server error response - type: object - properties: - error: - type: string - message: - type: string - required: - - error - additionalProperties: false - AssetList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - type: object - properties: - assetId: - type: string - originalFilename: - type: string - assetType: - type: string - size: - type: number - brandAgentId: - type: string - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - signedUrl: - type: string - tags: - type: array - items: - type: string - required: - - assetId - - originalFilename - - assetType - - size - - brandAgentId - - customerId - - signedUrl - additionalProperties: false - required: - - total - - items - additionalProperties: false - BrandAgentList: - type: object - properties: - brandAgents: - type: array - items: - $ref: '#/components/schemas/BrandAgentUpdateOutput' - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - brandAgents - - total - additionalProperties: false - BrandAgentDelete: - type: object - properties: - success: - type: boolean - deletedId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - required: - - success - - deletedId - additionalProperties: false - BrandStandardsDelete: - type: object - properties: - success: - type: boolean - id: - type: string - required: - - success - - id - additionalProperties: false - BrandStandardsList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - $ref: '#/components/schemas/BrandStandardsCreateOutput' - required: - - total - - items - additionalProperties: false - BrandStoryCreate: - type: object - properties: - id: - type: string - name: - type: string - brandAgentId: - type: string - countryCodes: - type: array - items: - type: string - channelCodes: - type: array - items: - type: string - languages: - type: array - items: - type: string - brands: - type: array - items: - type: string - currentModel: - type: object - properties: - id: - type: string - name: - type: string - prompt: - type: string - status: - nullable: true - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - prompt - - status - - createdAt - - updatedAt - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - createdAt - - updatedAt - additionalProperties: false - BrandStoryUpdate: - type: object - properties: - id: - type: string - name: - type: string - prompt: - type: string - status: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - createdAt - - updatedAt - additionalProperties: false - BrandStoryDelete: - type: object - properties: - success: - type: boolean - id: - type: string - required: - - success - - id - additionalProperties: false - BrandStoryList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - type: object - properties: - id: - type: string - name: - type: string - description: - type: string - status: - type: string - type: - type: string - languages: - type: array - items: - type: string - currentModel: - type: object - properties: - id: - type: string - name: - type: string - prompt: - type: string - status: - nullable: true - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - prompt - - status - - createdAt - - updatedAt - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - status - - type - - languages - - createdAt - - updatedAt - additionalProperties: false - required: - - total - - items - additionalProperties: false - CampaignList: - type: object - properties: - campaigns: - type: array - items: - $ref: '#/components/schemas/CampaignUpdateOutput' - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - campaigns - - total - additionalProperties: false - CampaignDelete: - type: object - properties: - success: - type: boolean - deletedId: - type: string - required: - - success - - deletedId - additionalProperties: false - CampaignGetSummary: - type: object - properties: - campaignId: - type: string - summary: - type: object - additionalProperties: {} - required: - - campaignId - - summary - additionalProperties: false - CampaignListTactics: - type: object - properties: - tactics: - type: array - items: {} - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - tactics - - total - additionalProperties: false - CampaignValidateBrief: - type: object - properties: - valid: - type: boolean - feedback: - type: string - required: - - valid - additionalProperties: false - ChannelList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - type: object - properties: - channel: - type: string - displayName: - type: string - required: - - channel - - displayName - additionalProperties: false - required: - - total - - items - additionalProperties: false - CreativeAssign: - type: object - properties: - success: - type: boolean - creativeId: - type: string - campaignId: - type: string - required: - - success - - creativeId - - campaignId - additionalProperties: false - CreativeDelete: - type: object - properties: - success: - type: boolean - id: - type: string - required: - - success - - id - additionalProperties: false - CreativeList: - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/CreativeGetOutput' - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - items - - total - additionalProperties: false - CreativeSyncSalesAgents: - type: object - properties: - success: - type: boolean - creativeId: - type: string - campaignId: - type: string - required: - - success - - creativeId - additionalProperties: false - MediaBuyDelete: - type: object - properties: - success: - type: boolean - id: - type: string - required: - - success - - id - additionalProperties: false - MediaBuyExecute: - type: object - properties: - success: - type: boolean - mediaBuyId: - type: string - status: - type: string - adcpMediaBuyId: - type: string - adcpStatus: - type: string - required: - - success - - mediaBuyId - - status - additionalProperties: false - MediaBuyList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - $ref: '#/components/schemas/MediaBuyGetOutput' - required: - - total - - items - additionalProperties: false - MediaBuyValidateBudget: - type: object - properties: - valid: - type: boolean - message: - type: string - required: - - valid - additionalProperties: false - NotificationsList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - hasMore: - type: boolean - items: - type: array - items: - type: object - properties: - id: - type: string - type: - type: string - data: - type: object - additionalProperties: {} - read: - type: boolean - acknowledged: - type: boolean - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - type - - data - - read - - acknowledged - - createdAt - additionalProperties: false - required: - - total - - hasMore - - items - additionalProperties: false - NotificationsMarkRead: - type: object - properties: - success: - type: boolean - notificationId: - type: string - required: - - success - - notificationId - additionalProperties: false - NotificationsMarkAcknowledged: - type: object - properties: - success: - type: boolean - notificationId: - type: string - required: - - success - - notificationId - additionalProperties: false - NotificationsMarkAllRead: - type: object - properties: - success: - type: boolean - count: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - success - - count - additionalProperties: false - MediaProductDiscover: - type: object - properties: - success: - type: boolean - productsFound: - type: integer - minimum: 0 - maximum: 9007199254740991 - productsSaved: - type: integer - minimum: 0 - maximum: 9007199254740991 - successfulAgents: - type: integer - minimum: 0 - maximum: 9007199254740991 - failedAgents: - type: integer - minimum: 0 - maximum: 9007199254740991 - products: - type: array - items: - type: object - properties: - productId: - type: string - name: - type: string - publisherName: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - deliveryType: - type: string - enum: - - guaranteed - - non_guaranteed - inventoryType: - type: string - enum: - - premium - - run_of_site - - targeted_package - creativeFormats: - anyOf: - - type: array - items: - type: string - - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - fixedCpm: - type: number - floorCpm: - type: number - targetCpm: - type: number - required: - - productId - - name - - publisherName - - deliveryType - - inventoryType - additionalProperties: false - required: - - success - - productsFound - - productsSaved - - successfulAgents - - failedAgents - - products - additionalProperties: false - MediaProductSave: - type: object - properties: - id: - type: string - productId: - type: string - name: - type: string - publisherId: - type: string - publisherName: - type: string - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - productId - - name - - publisherId - - publisherName - - customerId - - createdAt - - updatedAt - additionalProperties: false - MediaProductList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - type: object - properties: - id: - type: string - productId: - type: string - name: - type: string - salesAgent: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - deliveryType: - type: string - enum: - - guaranteed - - non_guaranteed - format: - type: string - creativeFormats: - anyOf: - - type: array - items: - type: string - - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - id - - productId - - name - - deliveryType - additionalProperties: false - required: - - total - - items - additionalProperties: false - MediaProductSync: - type: object - properties: - success: - type: boolean - productsSaved: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - success - - productsSaved - additionalProperties: false - AgentGet: - anyOf: - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - authenticationType: - type: string - description: - type: string - organizationId: - type: string - registeredBy: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - - authenticationType - - createdAt - - updatedAt - additionalProperties: false - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - authenticationType: - type: string - description: - type: string - organizationId: - type: string - registeredBy: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - customerAccountCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - - authenticationType - - createdAt - - updatedAt - - customerAccountCount - additionalProperties: false - AgentList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - anyOf: - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - additionalProperties: false - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - customerAccountCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - - customerAccountCount - additionalProperties: false - required: - - total - - items - additionalProperties: false - AgentRegister: - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - endpointUrl: - type: string - required: - - agentId - - name - - type - - status - - endpointUrl - additionalProperties: false - AgentUnregister: - type: object - properties: - success: - type: boolean - agentId: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - required: - - success - - agentId - - type - additionalProperties: false - AgentUpdate: - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - required: - - agentId - - name - - type - - status - additionalProperties: false - SalesAgentGet: - type: object - properties: - agentId: - type: string - name: - type: string - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - authenticationType: - type: string - description: - type: string - customerAccountCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - organizationId: - type: string - registeredBy: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - agentId - - name - - status - - relationship - - endpointUrl - - protocol - - authenticationType - - customerAccountCount - - createdAt - - updatedAt - additionalProperties: false - SalesAgentList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - type: object - properties: - agentId: - type: string - name: - type: string - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - customerAccountCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - agentId - - name - - status - - relationship - - endpointUrl - - protocol - - customerAccountCount - additionalProperties: false - required: - - total - - items - additionalProperties: false - SalesAgentRegister: - type: object - properties: - agentId: - type: string - name: - type: string - status: - type: string - endpointUrl: - type: string - required: - - agentId - - name - - status - - endpointUrl - additionalProperties: false - SalesAgentUnregister: - type: object - properties: - success: - type: boolean - agentId: - type: string - required: - - success - - agentId - additionalProperties: false - SalesAgentUpdate: - type: object - properties: - agentId: - type: string - name: - type: string - status: - type: string - required: - - agentId - - name - - status - additionalProperties: false - SalesAgentAccountList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - type: object - properties: - id: - type: string - accountIdentifier: - type: string - status: - type: string - registeredBy: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - accountIdentifier - - status - - createdAt - - updatedAt - additionalProperties: false - required: - - total - - items - additionalProperties: false - SalesAgentAccountRegister: - type: object - properties: - accountId: - type: string - adcpAgentId: - type: string - status: - type: string - required: - - accountId - - adcpAgentId - - status - additionalProperties: false - SalesAgentAccountUnregister: - type: object - properties: - success: - type: boolean - agentId: - type: string - required: - - success - - agentId - additionalProperties: false - SalesAgentAccountUpdate: - type: object - properties: - id: - type: string - status: - type: string - required: - - id - - status - additionalProperties: false - TacticCreate: - type: object - properties: - id: - type: number - name: - type: string - prompt: - type: string - campaignId: - type: string - channelCodes: - type: array - items: - type: string - countryCodes: - type: array - items: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - campaignId - - channelCodes - - countryCodes - - createdAt - additionalProperties: false - TacticDelete: - type: object - properties: - success: - type: boolean - tacticId: - type: number - required: - - success - - tacticId - additionalProperties: false - TacticList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - $ref: '#/components/schemas/TacticGetOutput' - required: - - total - - items - additionalProperties: false - TacticLinkCampaign: - type: object - properties: - success: - type: boolean - tacticId: - type: number - campaignId: - type: string - required: - - success - - tacticId - - campaignId - additionalProperties: false - TacticUnlinkCampaign: - type: object - properties: - success: - type: boolean - tacticId: - type: number - campaignId: - type: string - required: - - success - - tacticId - - campaignId - additionalProperties: false - WebhookRegister: - type: object - properties: - id: - type: string - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - endpoint: - type: object - properties: - url: - type: string - method: - type: string - authenticationType: - type: string - required: - - url - - method - additionalProperties: false - eventTypes: - type: array - items: - type: string - filters: - type: object - properties: - campaigns: - type: array - items: - type: string - tactics: - type: array - items: - type: string - creatives: - type: array - items: - type: string - mediaBuys: - type: array - items: - type: string - metrics: - type: array - items: - type: string - minSeverity: - type: string - additionalProperties: false - retryPolicy: - type: object - properties: - maxRetries: - type: integer - minimum: 0 - maximum: 9007199254740991 - backoffMultiplier: - type: number - minimum: 0 - exclusiveMinimum: true - maxBackoffSeconds: - type: number - minimum: 0 - exclusiveMinimum: true - required: - - maxRetries - - backoffMultiplier - - maxBackoffSeconds - additionalProperties: false - status: - type: string - testResult: - type: object - properties: - success: - type: boolean - statusCode: - type: integer - minimum: -9007199254740991 - maximum: 9007199254740991 - error: - type: string - required: - - success - additionalProperties: false - required: - - id - - endpoint - - eventTypes - - retryPolicy - - status - - testResult - additionalProperties: false - WebhookList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - items: - type: array - items: - type: object - properties: - id: - type: string - status: - type: string - endpoint: - type: object - properties: - url: - type: string - method: - type: string - authenticationType: - type: string - required: - - url - - method - additionalProperties: false - eventTypes: - type: array - items: - type: string - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - failureCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - lastSuccess: - nullable: true - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - lastFailure: - nullable: true - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - status - - endpoint - - eventTypes - - failureCount - - createdAt - additionalProperties: false - required: - - total - - items - additionalProperties: false - WebhookDelete: - type: object - properties: - success: - type: boolean - webhookId: - type: string - required: - - success - - webhookId - additionalProperties: false - BrandAgentUpdateOutput: - type: object - properties: - id: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - name: - type: string - description: - type: string - manifestUrl: - type: string - format: uri - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - customerId - - createdAt - - updatedAt - additionalProperties: false - BrandStandardsCreateOutput: - type: object - properties: - id: - type: string - name: - type: string - description: - type: string - countryCodes: - type: array - items: - type: string - channelCodes: - type: array - items: - type: string - brands: - type: array - items: - type: string - models: - type: array - items: - type: object - properties: - id: - type: string - name: - type: string - prompt: - type: string - status: - nullable: true - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - prompt - - status - - createdAt - - updatedAt - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - countryCodes - - channelCodes - - brands - - models - - createdAt - - updatedAt - additionalProperties: false - CampaignUpdateOutput: - type: object - properties: - campaignId: - type: string - name: - type: string - status: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - campaignId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - CreativeGetOutput: - type: object - properties: - creativeId: - type: string - name: - type: string - status: - type: string - campaignId: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - creativeId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - MediaBuyGetOutput: - type: object - properties: - id: - type: string - tacticId: - type: number - customerId: - type: number - name: - type: string - description: - type: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - mediaProductId - - salesAgentId - additionalProperties: false - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - additionalProperties: false - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - additionalProperties: false - status: - type: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - additionalProperties: false - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - additionalProperties: false - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - additionalProperties: false - TacticGetOutput: - type: object - properties: - id: - type: number - name: - type: string - prompt: - type: string - campaignIds: - type: array - items: - type: string - channelCodes: - type: array - items: - type: string - countryCodes: - type: array - items: - type: string - mediaBuyCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - channelCodes - - countryCodes - - createdAt - - updatedAt - additionalProperties: false - BrandAgentGet: - type: object - properties: - id: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - name: - type: string - description: - type: string - manifestUrl: - type: string - format: uri - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - customerId - - createdAt - - updatedAt - additionalProperties: false - BrandAgentCreate: - type: object - properties: - id: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - name: - type: string - description: - type: string - manifestUrl: - type: string - format: uri - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - customerId - - createdAt - - updatedAt - additionalProperties: false - CampaignCreate: - type: object - properties: - campaignId: - type: string - name: - type: string - status: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - campaignId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - CampaignGet: - type: object - properties: - campaignId: - type: string - name: - type: string - status: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - campaignId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - CreativeCreate: - type: object - properties: - creativeId: - type: string - name: - type: string - status: - type: string - campaignId: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - creativeId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - CreativeUpdate: - type: object - properties: - creativeId: - type: string - name: - type: string - status: - type: string - campaignId: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - creativeId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - MediaBuyCreate: - type: object - properties: - id: - type: string - tacticId: - type: number - customerId: - type: number - name: - type: string - description: - type: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - mediaProductId - - salesAgentId - additionalProperties: false - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - additionalProperties: false - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - additionalProperties: false - status: - type: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - additionalProperties: false - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - additionalProperties: false - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - additionalProperties: false - MediaBuyUpdate: - type: object - properties: - id: - type: string - tacticId: - type: number - customerId: - type: number - name: - type: string - description: - type: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - mediaProductId - - salesAgentId - additionalProperties: false - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - additionalProperties: false - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - additionalProperties: false - status: - type: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - additionalProperties: false - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - additionalProperties: false - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - additionalProperties: false - TacticUpdate: - type: object - properties: - id: - type: number - name: - type: string - prompt: - type: string - campaignIds: - type: array - items: - type: string - channelCodes: - type: array - items: - type: string - countryCodes: - type: array - items: - type: string - mediaBuyCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - channelCodes - - countryCodes - - createdAt - - updatedAt - additionalProperties: false - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT diff --git a/outcome-agent-openapi.yaml b/outcome-agent-openapi.yaml deleted file mode 100644 index 2bfd1b0..0000000 --- a/outcome-agent-openapi.yaml +++ /dev/null @@ -1,375 +0,0 @@ -openapi: 3.0.0 -info: - title: Outcome Agent Protocol - version: 1.0.0 - description: | - Protocol specification for outcome agents to implement on their own infrastructure. - - Outcome agents are autonomous systems that manage tactics and optimize media buying to achieve - campaign outcomes on behalf of advertisers. When you build an outcome agent, you implement - these endpoints on YOUR servers, and Scope3's platform will call them to get proposals, - assign tactics, and send updates. - - This is similar to how sales agents work - you implement the protocol on your infrastructure, - not in Scope3's codebase. - -servers: - - url: https://outcome-agent.yourcompany.com - description: Your outcome agent server (you implement this) - -tags: - - name: Proposals - description: Endpoints Scope3 calls to get your proposals - - name: Tactic Management - description: Endpoints for managing assigned tactics - -paths: - /get-proposals: - post: - tags: [Proposals] - summary: Get proposals from your agent - operationId: get_proposed_tactics - description: | - Scope3 calls this endpoint when setting up a campaign to ask for proposals - from your agent on how you would approach execution. - - Analyze the campaign and respond with proposals, budget capacity, - and your pricing model. - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GetProposalsRequest' - responses: - '200': - description: Proposals from your agent - content: - application/json: - schema: - $ref: '#/components/schemas/GetProposalsResponse' - '400': - description: Invalid request - '500': - description: Internal error - - /accept-proposal: - post: - tags: [Tactic Management] - summary: Accept or decline proposal assignment - operationId: accept_proposal - description: | - Scope3 calls this when your proposal is accepted and you are assigned to manage a tactic. - You should acknowledge and begin setup, or decline if you can't fulfill it. - - The campaign context contains everything you need: budget, schedule, - targeting constraints, creatives, and any custom fields. - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AcceptProposalRequest' - responses: - '200': - description: Acknowledgment of tactic assignment - content: - application/json: - schema: - $ref: '#/components/schemas/AcceptProposalResponse' - '400': - description: Invalid request - -components: - securitySchemes: - apiKey: - type: apiKey - in: header - name: X-API-Key - description: API key for authenticating Scope3's requests to your server - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - description: JWT bearer token for OAuth-based authentication - basic: - type: http - scheme: basic - description: Basic authentication with username/password - - schemas: - BudgetRange: - type: object - description: Budget range for campaign planning (buyer typically won't reveal full budget) - properties: - min: - type: number - description: Minimum budget available - example: 50000 - max: - type: number - description: Maximum budget available - example: 150000 - currency: - type: string - description: Currency for budget (ISO 4217 code) - default: USD - example: USD - - TacticPricing: - type: object - required: - - method - - rate - properties: - method: - type: string - enum: [revshare, cost_per_unit] - description: How the outcome agent charges for this tactic (revshare or cost_per_unit) - example: revshare - rate: - type: number - description: Rate for the pricing method (e.g., 0.15 for 15% revshare, 2.50 for $2.50 CPM) - example: 0.15 - unit: - type: string - enum: [cpm, cpc, cpa, cpv, cpcv] - description: Pricing unit (required when method is cost_per_unit) - example: cpm - currency: - type: string - description: Currency for pricing (ISO 4217 code) - default: USD - example: USD - - CustomField: - type: object - properties: - fieldName: - type: string - description: Name of the custom field - example: targetVCPM - fieldType: - type: string - enum: [string, number, boolean, array, object] - description: Data type of the field - example: number - description: - type: string - description: Help text explaining what this field does - example: Target vCPM in USD - - Product: - type: object - description: Product reference from sales agent - required: - - sales_agent_url - - product_ref - - pricing_option_id - properties: - sales_agent_url: - type: string - description: URL of the sales agent offering this product - example: https://sales-agent.example.com - product_ref: - type: string - description: Product reference ID from the sales agent - example: prod_premium_display - pricing_option_id: - type: string - description: Pricing option ID for this product - example: pricing_opt_123 - - GetProposalsRequest: - type: object - required: - - campaignId - - seatId - properties: - campaignId: - type: string - description: Campaign ID - example: camp_123 - budgetRange: - $ref: '#/components/schemas/BudgetRange' - startDate: - type: string - format: date-time - description: Campaign start date in UTC (ISO 8601 format) - example: '2025-01-01T00:00:00Z' - endDate: - type: string - format: date-time - description: Campaign end date in UTC (ISO 8601 format) - example: '2025-01-31T23:59:59Z' - channels: - type: array - items: - type: string - enum: [display, video, native, audio, connected_tv] - description: Advertising channels (from ADCP specification) - example: [display, video] - countries: - type: array - items: - type: string - description: ISO 3166-1 alpha-2 country codes - example: [US, CA] - brief: - type: string - description: Campaign brief text - example: Launch campaign for new product... - products: - type: array - items: - $ref: '#/components/schemas/Product' - description: Optional product objects to include in proposals (full product details, not just IDs) - propertyListIds: - type: array - items: - type: integer - format: int64 - description: Optional property list IDs for targeting (references Scope3 property lists) - example: [123, 456] - seatId: - type: string - description: Seat/account ID for this request - example: seat_456 - - Proposal: - type: object - required: - - proposalId - - execution - - budgetCapacity - - pricing - properties: - proposalId: - type: string - description: Unique identifier for this proposal (you generate this). The tactic ID will be assigned when the proposal is accepted. - example: premium-vcpm-display - execution: - type: string - description: How you would execute this proposal - example: Target premium inventory at $2.50 vCPM with 85% viewability - budgetCapacity: - type: number - description: Maximum budget you can effectively manage - example: 50000 - pricing: - $ref: '#/components/schemas/TacticPricing' - sku: - type: string - description: Identifier for this tactic type - example: premium-vcpm - customFieldsRequired: - type: array - items: - $ref: '#/components/schemas/CustomField' - description: Custom fields needed to execute this proposal - additional_info: - type: object - description: Generic blob to store additional information about the proposal that will be passed back when accepted - example: { "property_list": ["prop1", "prop2"], "custom_data": "value" } - - GetProposalsResponse: - type: object - properties: - proposals: - type: array - items: - $ref: '#/components/schemas/Proposal' - description: List of proposals you can provide (empty array if none) - - CampaignContext: - type: object - properties: - budget: - type: number - description: Budget allocated - example: 50000 - budgetCurrency: - type: string - description: Currency for budget (ISO 4217 code) - default: USD - example: USD - startDate: - type: string - format: date-time - description: Campaign start date in UTC (ISO 8601 format) - example: '2025-01-01T00:00:00Z' - endDate: - type: string - format: date-time - description: Campaign end date in UTC (ISO 8601 format) - example: '2025-01-31T23:59:59Z' - channel: - type: string - enum: [display, video, native, audio, connected_tv] - description: Advertising channel (from ADCP specification) - example: display - countries: - type: array - items: - type: string - description: Target countries - example: [US] - creatives: - type: array - items: - $ref: '#/components/schemas/Creative' - description: Creative assets to use (uses Creative from main schema) - brandStandards: - type: array - items: - $ref: '#/components/schemas/BrandStandard' - description: Brand safety and suitability requirements (uses BrandStandard from main schema) - - AcceptProposalRequest: - type: object - required: - - tacticId - - campaignContext - - brandAgentId - - seatId - properties: - tacticId: - type: string - description: ID of the tactic from the strategy table (assigned when user accepts your proposal) - example: "12345" - proposalId: - type: string - description: ID of the proposal that was accepted (matches proposalId from GetProposalsResponse) - example: premium-vcpm-display - campaignContext: - $ref: '#/components/schemas/CampaignContext' - brandAgentId: - type: string - description: Brand agent (advertiser) for this campaign - example: ba_123 - seatId: - type: string - description: Seat/account ID - example: seat_456 - customFields: - type: object - description: Custom fields provided by advertiser - example: { targetVCPM: 2.5 } - additional_info: - type: object - description: The additional_info blob that was returned in the proposal response - example: { "property_list": ["prop1", "prop2"], "custom_data": "value" } - - AcceptProposalResponse: - type: object - required: - - acknowledged - properties: - acknowledged: - type: boolean - description: true to accept assignment, false to decline - example: true - reason: - type: string - description: Optional reason if declining - example: Insufficient budget for effective optimization diff --git a/package-lock.json b/package-lock.json index 6363644..89114ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,41 +1,35 @@ { "name": "scope3", - "version": "1.1.0", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "scope3", - "version": "1.1.0", + "version": "2.0.0", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.20.1", "chalk": "^4.1.2", "cli-table3": "^0.6.5", "commander": "^14.0.2", - "express": "^4.18.0", - "fastmcp": "^3.20.2", - "zod": "^3.25.76" + "express": "^4.18.0" }, "bin": { - "scope3": "dist/cli.js", - "simple-media-agent": "dist/simple-media-agent-server.js" + "scope3": "dist/cli/index.js" }, "devDependencies": { "@changesets/changelog-github": "^0.5.1", "@changesets/cli": "^2.29.7", "@types/express": "^4.17.0", "@types/jest": "^29.5.0", - "@types/js-yaml": "^4.0.9", "@types/node": "^20.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.0.0", "husky": "^9.0.0", "jest": "^29.5.0", - "js-yaml": "^4.1.0", "lint-staged": "^15.0.0", - "openapi-typescript": "^6.7.0", "prettier": "^3.0.0", "ts-jest": "^29.1.0", "ts-node": "^10.9.2", @@ -568,16 +562,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@borewit/text-codec": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.1.1.tgz", - "integrity": "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/@changesets/apply-release-plan": { "version": "7.0.13", "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.13.tgz", @@ -1057,16 +1041,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", @@ -2098,12 +2072,6 @@ "node": ">= 8" } }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", - "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", - "license": "MIT" - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -2111,18 +2079,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -2143,36 +2099,6 @@ "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "license": "MIT" - }, - "node_modules/@tokenizer/inflate": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", - "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "fflate": "^0.8.2", - "token-types": "^6.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "license": "MIT" - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -2268,22 +2194,22 @@ } }, "node_modules/@types/express": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", - "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", "dev": true, "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", - "@types/serve-static": "*" + "@types/serve-static": "^1" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz", - "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==", + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", "dev": true, "license": "MIT", "dependencies": { @@ -2348,13 +2274,6 @@ "pretty-format": "^29.0.0" } }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -2401,9 +2320,9 @@ "license": "MIT" }, "node_modules/@types/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.0.tgz", - "integrity": "sha512-zBF6vZJn1IaMpg3xUF25VK3gd3l8zwE0ZLRX7dsQyQi+jp4E8mMDJNGDYnYse+bQhYwWERTxVwHpi3dMOq7RKQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2411,9 +2330,9 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.9.tgz", - "integrity": "sha512-dOTIuqpWLyl3BBXU3maNQsS4A3zuuoYRNIvYSxxhebPfXg2mzWQEPne/nlJ37yOse6uGgR386uTpdsx4D0QZWA==", + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", "dev": true, "license": "MIT", "dependencies": { @@ -2423,9 +2342,9 @@ } }, "node_modules/@types/serve-static/node_modules/@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", "dev": true, "license": "MIT", "dependencies": { @@ -3803,6 +3722,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -4235,273 +4155,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fastmcp": { - "version": "3.20.2", - "resolved": "https://registry.npmjs.org/fastmcp/-/fastmcp-3.20.2.tgz", - "integrity": "sha512-5oQGAMZbxARnChEsfEq8l0O7XrBLCDQaZV0f9QGLXaPn+xjl9xPGJRzMhmuVB++2WTEoC5Ue6AtrvZYDPFSJiw==", - "license": "MIT", - "dependencies": { - "@modelcontextprotocol/sdk": "^1.17.2", - "@standard-schema/spec": "^1.0.0", - "execa": "^9.6.0", - "file-type": "^21.0.0", - "fuse.js": "^7.1.0", - "mcp-proxy": "^5.8.1", - "strict-event-emitter-types": "^2.0.0", - "undici": "^7.13.0", - "uri-templates": "^0.2.0", - "xsschema": "0.4.0-beta.5", - "yargs": "^18.0.0", - "zod": "^3.25.76", - "zod-to-json-schema": "^3.24.6" - }, - "bin": { - "fastmcp": "dist/bin/fastmcp.js" - } - }, - "node_modules/fastmcp/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/fastmcp/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/fastmcp/node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/fastmcp/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/fastmcp/node_modules/execa": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.0.tgz", - "integrity": "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==", - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.6", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.1", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.2.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/fastmcp/node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fastmcp/node_modules/human-signals": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", - "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/fastmcp/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fastmcp/node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fastmcp/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fastmcp/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fastmcp/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fastmcp/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/fastmcp/node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fastmcp/node_modules/undici": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", - "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/fastmcp/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/fastmcp/node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", - "license": "MIT", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/fastmcp/node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, "node_modules/fastq": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", @@ -4522,27 +4175,6 @@ "bser": "2.1.1" } }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT" - }, - "node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -4556,24 +4188,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-type": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz", - "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==", - "license": "MIT", - "dependencies": { - "@tokenizer/inflate": "^0.2.7", - "strtok3": "^10.2.2", - "token-types": "^6.0.0", - "uint8array-extras": "^1.4.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -4723,15 +4337,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fuse.js": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz", - "integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4746,6 +4351,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -4755,6 +4361,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -5071,26 +4678,6 @@ "node": ">=0.10.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -5260,18 +4847,6 @@ "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -5304,18 +4879,6 @@ "node": ">=4" } }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -6674,15 +6237,6 @@ "node": ">= 0.4" } }, - "node_modules/mcp-proxy": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/mcp-proxy/-/mcp-proxy-5.9.0.tgz", - "integrity": "sha512-xonJSkuy4wmwXeykBFl0mjRMt4D0pAGCtFIfBFUz4O80VrO92ruJseIdASJO3wN6MdYHi3vbZLOQol3NsUpg4g==", - "license": "MIT", - "bin": { - "mcp-proxy": "dist/bin/mcp-proxy.js" - } - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -6978,37 +6532,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openapi-typescript": { - "version": "6.7.6", - "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-6.7.6.tgz", - "integrity": "sha512-c/hfooPx+RBIOPM09GSxABOZhYPblDoyaGhqBkD/59vtpN21jEuWKDlM0KYTvqJVlSYjKs0tBcIdeXKChlSPtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.3", - "fast-glob": "^3.3.2", - "js-yaml": "^4.1.0", - "supports-color": "^9.4.0", - "undici": "^5.28.4", - "yargs-parser": "^21.1.1" - }, - "bin": { - "openapi-typescript": "bin/cli.js" - } - }, - "node_modules/openapi-typescript/node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -7141,18 +6664,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -7399,21 +6910,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/pretty-ms": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", - "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", - "license": "MIT", - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -8158,12 +7654,6 @@ "node": ">= 0.8" } }, - "node_modules/strict-event-emitter-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", - "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==", - "license": "ISC" - }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -8247,22 +7737,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strtok3": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", - "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", - "license": "MIT", - "dependencies": { - "@tokenizer/token": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -8376,24 +7850,6 @@ "node": ">=0.6" } }, - "node_modules/token-types": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz", - "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==", - "license": "MIT", - "dependencies": { - "@borewit/text-codec": "^0.1.0", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -8601,31 +8057,6 @@ "node": ">=0.8.0" } }, - "node_modules/uint8array-extras": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", - "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -8633,18 +8064,6 @@ "dev": true, "license": "MIT" }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -8704,12 +8123,6 @@ "punycode": "^2.1.0" } }, - "node_modules/uri-templates": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/uri-templates/-/uri-templates-0.2.0.tgz", - "integrity": "sha512-EWkjYEN0L6KOfEoOH6Wj4ghQqU7eBZMJqRHQnxQAq+dSEzRPClkWjf8557HkWQXF6BrAUoLSAyy9i3RVTliaNg==", - "license": "http://geraintluff.github.io/tv4/LICENSE.txt" - }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -8848,44 +8261,11 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/xsschema": { - "version": "0.4.0-beta.5", - "resolved": "https://registry.npmjs.org/xsschema/-/xsschema-0.4.0-beta.5.tgz", - "integrity": "sha512-73pYwf1hMy++7SnOkghJdgdPaGi+Y5I0SaO6rIlxb1ouV6tEyDbEcXP82kyr32KQVTlUbFj6qewi9eUVEiXm+g==", - "license": "MIT", - "peerDependencies": { - "@valibot/to-json-schema": "^1.0.0", - "arktype": "^2.1.20", - "effect": "^3.16.0", - "sury": "^10.0.0", - "zod": "^3.25.0 || ^4.0.0", - "zod-to-json-schema": "^3.24.5" - }, - "peerDependenciesMeta": { - "@valibot/to-json-schema": { - "optional": true - }, - "arktype": { - "optional": true - }, - "effect": { - "optional": true - }, - "sury": { - "optional": true - }, - "zod": { - "optional": true - }, - "zod-to-json-schema": { - "optional": true - } - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -8963,18 +8343,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", diff --git a/package.json b/package.json index dfe801a..491e755 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,22 @@ { "name": "scope3", - "version": "1.1.0", - "description": "CLI and TypeScript client for the Scope3 Agentic API with AdCP webhook support", + "version": "2.0.0", + "description": "Scope3 SDK - REST and MCP client for the Agentic Platform", + "engines": { + "node": ">=18" + }, "main": "dist/index.js", "types": "dist/index.d.ts", "files": [ "dist", - "scripts", "README.md", - "LICENSE", - ".env.example" + "LICENSE" ], "publishConfig": { "access": "public" }, "bin": { - "scope3": "dist/cli.js" + "scope3": "dist/cli/index.js" }, "scripts": { "build": "npm run type-check && tsc", @@ -24,12 +25,12 @@ "lint": "eslint src --ext .ts", "format": "prettier --write \"src/**/*.ts\"", "type-check": "tsc --noEmit", - "generate-outcome-agent-types": "openapi-typescript outcome-agent-openapi.yaml -o src/types/outcome-agent-api.ts", - "generate-partner-api-types": "openapi-typescript partner-api.yaml -o src/types/partner-api.ts", - "generate-platform-api-types": "openapi-typescript platform-api.yaml -o src/types/platform-api.ts", - "generate-sdk": "ts-node scripts/generate-sdk.ts", - "generate-all": "npm run generate-outcome-agent-types && npm run generate-partner-api-types && npm run generate-platform-api-types && npm run generate-sdk", - "update-schemas": "bash scripts/update-schemas.sh", + "bundle-skill": "ts-node scripts/bundle-skill.ts", + "test:buyer": "./scripts/test-buyer-workflow.sh", + "test:brand": "./scripts/test-brand-workflow.sh", + "test:partner": "./scripts/test-partner-workflow.sh", + "test:sdk": "ts-node scripts/test-sdk-workflow.ts", + "test:all": "npm run test:buyer && npm run test:brand && npm run test:partner", "prepare": "husky", "prepublishOnly": "npm run build", "pretest": "npm run type-check", @@ -41,8 +42,11 @@ "scope3", "advertising", "agentic", - "adcp", - "typescript" + "sdk", + "mcp", + "rest", + "typescript", + "cli" ], "author": "", "license": "MIT", @@ -60,25 +64,20 @@ "chalk": "^4.1.2", "cli-table3": "^0.6.5", "commander": "^14.0.2", - "express": "^4.18.0", - "fastmcp": "^3.20.2", - "zod": "^3.25.76" + "express": "^4.18.0" }, "devDependencies": { "@changesets/changelog-github": "^0.5.1", - "@changesets/cli": "^2.29.7", "@types/express": "^4.17.0", + "@changesets/cli": "^2.29.7", "@types/jest": "^29.5.0", - "@types/js-yaml": "^4.0.9", "@types/node": "^20.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.0.0", "husky": "^9.0.0", "jest": "^29.5.0", - "js-yaml": "^4.1.0", "lint-staged": "^15.0.0", - "openapi-typescript": "^6.7.0", "prettier": "^3.0.0", "ts-jest": "^29.1.0", "ts-node": "^10.9.2", diff --git a/partner-api.yaml b/partner-api.yaml deleted file mode 100644 index f74929f..0000000 --- a/partner-api.yaml +++ /dev/null @@ -1,6964 +0,0 @@ -# This OpenAPI specification is auto-generated from TypeScript Schemas -# DO NOT EDIT THIS FILE MANUALLY -# API Type: PARTNER - -openapi: 3.0.0 -info: - title: Scope3 Partner API - version: 1.0.0 - description: |- - API for partners to register agents, manage tactics and media buys, and configure webhooks. - - This API provides partners with tools to: - - Register and manage sales agents (DSPs, publisher platforms) - - Full CRUD operations for tactics and media buys - - Link tactics to buyer campaigns (read-only campaign access) - - Manage media products and product discovery - - Configure webhooks for event notifications - - Execute media buys and manage placements -servers: - - url: https://api.agentic.scope3.com/mcp - description: Production server - - url: https://api.agentic.staging.scope3.com/mcp - description: Staging server -paths: - /mcp-initialize: - post: - operationId: mcp_initialize - summary: Initialize MCP session - description: >- - Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as - a UUID and included in the mcp-session-id header for all subsequent requests. - tags: - - MCP - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: MCP session identifier (UUID). Generate a new UUID for session initialization. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - jsonrpc: - type: string - enum: - - '2.0' - id: - oneOf: - - type: string - - type: number - method: - type: string - enum: - - initialize - params: - type: object - properties: - protocolVersion: - type: string - example: '2024-11-05' - capabilities: - type: object - clientInfo: - type: object - properties: - name: - type: string - version: - type: string - required: - - name - - version - required: - - protocolVersion - - capabilities - - clientInfo - required: - - jsonrpc - - id - - method - - params - responses: - '200': - description: Session initialized successfully - content: - application/json: - schema: - type: object - properties: - jsonrpc: - type: string - enum: - - '2.0' - id: - oneOf: - - type: string - - type: number - result: - type: object - properties: - protocolVersion: - type: string - capabilities: - type: object - serverInfo: - type: object - properties: - name: - type: string - version: - type: string - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - /channel-list: - post: - operationId: channel_list - summary: List channels - description: List all available advertising channels and platforms. - tags: - - Channels - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for channel_list - required: true - content: - application/json: - example: - tool: channel_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - channel_list - arguments: - $ref: '#/components/schemas/ListChannelsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/ChannelList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /country-list: - post: - operationId: country_list - summary: List countries - description: Get all available countries for targeting. Use this to get valid country codes before creating brand agents. - tags: - - Targeting - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for country_list - required: true - content: - application/json: - example: - tool: country_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - country_list - arguments: - $ref: '#/components/schemas/ListCountriesInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CountryList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /language-list: - post: - operationId: language_list - summary: List languages - description: Get all available languages for targeting. Use this to get valid language codes before creating brand stories. - tags: - - Targeting - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for language_list - required: true - content: - application/json: - example: - tool: language_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - language_list - arguments: - $ref: '#/components/schemas/ListLanguagesInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/LanguageList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-sync-sales-agents: - post: - operationId: creative_sync_sales_agents - summary: Sync creatives to sales agents - description: Synchronize creatives to connected sales agents (DSPs, publisher platforms). - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for creative_sync_sales_agents - required: true - content: - application/json: - example: - tool: creative_sync_sales_agents - arguments: - creativeId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - creative_sync_sales_agents - arguments: - $ref: '#/components/schemas/SyncSalesAgentsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeSyncSalesAgents' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-create: - post: - operationId: media_buy_create - summary: Create media buy - description: Create a new media buy with budget, targeting, and creative specifications. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_buy_create - required: true - content: - application/json: - example: - tool: media_buy_create - arguments: - tacticId: 100 - agentId: example_id_123 - name: Example Name - products: [] - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_create - arguments: - $ref: '#/components/schemas/CreateMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-update: - post: - operationId: media_buy_update - summary: Update media buy - description: Update an existing media buy with new budget, targeting, or creative assignments. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_buy_update - required: true - content: - application/json: - example: - tool: media_buy_update - arguments: - mediaBuyId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_update - arguments: - $ref: '#/components/schemas/UpdateMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-delete: - post: - operationId: media_buy_delete - summary: Delete media buy - description: Delete a media buy and cancel any active placements. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_buy_delete - required: true - content: - application/json: - example: - tool: media_buy_delete - arguments: - mediaBuyId: example_id_123 - confirm: true - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_delete - arguments: - $ref: '#/components/schemas/DeleteMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-execute: - post: - operationId: media_buy_execute - summary: Execute media buy - description: Execute a media buy, sending it to the configured sales agents for placement. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_buy_execute - required: true - content: - application/json: - example: - tool: media_buy_execute - arguments: - mediaBuyId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_execute - arguments: - $ref: '#/components/schemas/ExecuteMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyExecute' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-get: - post: - operationId: media_buy_get - summary: Get media buy - description: Get detailed information about a specific media buy. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_buy_get - required: true - content: - application/json: - example: - tool: media_buy_get - arguments: - mediaBuyId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_get - arguments: - $ref: '#/components/schemas/GetMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-list: - post: - operationId: media_buy_list - summary: List media buys - description: List all media buys with optional filtering by brand agent, campaign, or status. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_buy_list - required: true - content: - application/json: - example: - tool: media_buy_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_list - arguments: - $ref: '#/components/schemas/ListMediaBuysInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-validate-budget: - post: - operationId: media_buy_validate_budget - summary: Validate media buy budget - description: Validate a media buy budget against campaign constraints and available funds. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_buy_validate_budget - required: true - content: - application/json: - example: - tool: media_buy_validate_budget - arguments: - tacticId: 100 - newBudgetAmount: 100 - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_validate_budget - arguments: - $ref: '#/components/schemas/ValidateMediaBuyBudgetInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyValidateBudget' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /notifications-list: - post: - operationId: notifications_list - summary: List notifications - description: List notifications for the authenticated user with optional filtering by status. - tags: - - Notifications - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for notifications_list - required: true - content: - application/json: - example: - tool: notifications_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - notifications_list - arguments: - $ref: '#/components/schemas/ListNotificationsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/NotificationsList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /notifications-mark-read: - post: - operationId: notifications_mark_read - summary: Mark notification as read - description: Mark a specific notification as read. - tags: - - Notifications - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for notifications_mark_read - required: true - content: - application/json: - example: - tool: notifications_mark_read - arguments: - notificationId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - notifications_mark_read - arguments: - $ref: '#/components/schemas/MarkNotificationReadInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/NotificationsMarkRead' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /notifications-mark-acknowledged: - post: - operationId: notifications_mark_acknowledged - summary: Mark notification as acknowledged - description: Mark a specific notification as acknowledged. - tags: - - Notifications - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for notifications_mark_acknowledged - required: true - content: - application/json: - example: - tool: notifications_mark_acknowledged - arguments: - notificationId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - notifications_mark_acknowledged - arguments: - $ref: '#/components/schemas/MarkNotificationAcknowledgedInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/NotificationsMarkAcknowledged' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /notifications-mark-all-read: - post: - operationId: notifications_mark_all_read - summary: Mark all notifications as read - description: Mark all notifications for the authenticated user as read. - tags: - - Notifications - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for notifications_mark_all_read - required: true - content: - application/json: - example: - tool: notifications_mark_all_read - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - notifications_mark_all_read - arguments: - $ref: '#/components/schemas/MarkAllNotificationsReadInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/NotificationsMarkAllRead' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-product-discover: - post: - operationId: media_product_discover - summary: Discover media products - description: Discover available media products from connected sales agents based on targeting criteria. - tags: - - Media Products - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_product_discover - required: true - content: - application/json: - example: - tool: media_product_discover - arguments: - brief: string - brandManifestUrl: https://example.com - schema: - type: object - properties: - tool: - type: string - enum: - - media_product_discover - arguments: - $ref: '#/components/schemas/DiscoverProductsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaProductDiscover' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-product-save: - post: - operationId: media_product_save - summary: Save media product - description: Save a discovered media product for future use in media buys. - tags: - - Media Products - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_product_save - required: true - content: - application/json: - example: - tool: media_product_save - arguments: - productId: example_id_123 - name: Example Name - description: string - publisherId: example_id_123 - publisherName: Example Name - deliveryType: guaranteed - inventoryType: premium - pricingModel: auction - schema: - type: object - properties: - tool: - type: string - enum: - - media_product_save - arguments: - $ref: '#/components/schemas/SaveProductInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaProductSave' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-product-list: - post: - operationId: media_product_list - summary: List media products - description: List saved media products with optional filtering. - tags: - - Media Products - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_product_list - required: true - content: - application/json: - example: - tool: media_product_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - media_product_list - arguments: - $ref: '#/components/schemas/ListProductsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaProductList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-product-sync: - post: - operationId: media_product_sync - summary: Sync media products - description: Synchronize media product catalog from connected sales agents. - tags: - - Media Products - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_product_sync - required: true - content: - application/json: - example: - tool: media_product_sync - arguments: - sourceId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - media_product_sync - arguments: - $ref: '#/components/schemas/SyncProductsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaProductSync' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-get: - post: - operationId: agent_get - summary: Get agent - description: >- - Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the - agent ID. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for agent_get - required: true - content: - application/json: - example: - tool: agent_get - arguments: - agentId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - agent_get - arguments: - $ref: '#/components/schemas/GetAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentGet' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-list: - post: - operationId: agent_list - summary: List agents - description: >- - List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, - organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for agent_list - required: true - content: - application/json: - example: - tool: agent_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - agent_list - arguments: - $ref: '#/components/schemas/ListAgentsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-register: - post: - operationId: agent_register - summary: Register agent - description: Register a new agent for media buying (SALES type) or outcome optimization (OUTCOME type). - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for agent_register - required: true - content: - application/json: - example: - tool: agent_register - arguments: - type: SALES - name: Example Name - endpointUrl: https://example.com - protocol: MCP - schema: - type: object - properties: - tool: - type: string - enum: - - agent_register - arguments: - $ref: '#/components/schemas/RegisterAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentRegister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-unregister: - post: - operationId: agent_unregister - summary: Unregister agent - description: Unregister an agent and disconnect it from the platform. Type is automatically inferred from the agent ID. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for agent_unregister - required: true - content: - application/json: - example: - tool: agent_unregister - arguments: - agentId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - agent_unregister - arguments: - $ref: '#/components/schemas/UnregisterAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentUnregister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-update: - post: - operationId: agent_update - summary: Update agent - description: Update agent configuration and credentials. Type is automatically inferred from the agent ID. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for agent_update - required: true - content: - application/json: - example: - tool: agent_update - arguments: - agentId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - agent_update - arguments: - $ref: '#/components/schemas/UpdateAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentUpdate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-create: - post: - operationId: tactic_create - summary: Create tactic - description: Create a new tactic defining how to achieve campaign objectives. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for tactic_create - required: true - content: - application/json: - example: - tool: tactic_create - arguments: - campaignId: example_id_123 - name: Example Name - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_create - arguments: - $ref: '#/components/schemas/CreateTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticCreate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-update: - post: - operationId: tactic_update - summary: Update tactic - description: Update an existing tactic with new targeting, budget, or creative requirements. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for tactic_update - required: true - content: - application/json: - example: - tool: tactic_update - arguments: - tacticId: 100 - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_update - arguments: - $ref: '#/components/schemas/UpdateTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-delete: - post: - operationId: tactic_delete - summary: Delete tactic - description: Delete a tactic and all associated media buys. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for tactic_delete - required: true - content: - application/json: - example: - tool: tactic_delete - arguments: - tacticId: 100 - confirm: true - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_delete - arguments: - $ref: '#/components/schemas/DeleteTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-get: - post: - operationId: tactic_get - summary: Get tactic - description: Get detailed information about a specific tactic. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for tactic_get - required: true - content: - application/json: - example: - tool: tactic_get - arguments: - tacticId: 100 - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_get - arguments: - $ref: '#/components/schemas/GetTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-list: - post: - operationId: tactic_list - summary: List tactics - description: List all tactics with optional filtering by brand agent or campaign. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for tactic_list - required: true - content: - application/json: - example: - tool: tactic_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_list - arguments: - $ref: '#/components/schemas/ListTacticsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-link-campaign: - post: - operationId: tactic_link_campaign - summary: Link tactic to campaign - description: Link a tactic to a campaign. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for tactic_link_campaign - required: true - content: - application/json: - example: - tool: tactic_link_campaign - arguments: - tacticId: 100 - campaignId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_link_campaign - arguments: - $ref: '#/components/schemas/LinkCampaignToTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticLinkCampaign' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-unlink-campaign: - post: - operationId: tactic_unlink_campaign - summary: Unlink tactic from campaign - description: Unlink a tactic from a campaign. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for tactic_unlink_campaign - required: true - content: - application/json: - example: - tool: tactic_unlink_campaign - arguments: - tacticId: 100 - campaignId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_unlink_campaign - arguments: - $ref: '#/components/schemas/UnlinkCampaignFromTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticUnlinkCampaign' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /webhook-register: - post: - operationId: webhook_register - summary: Register webhook - description: Register a webhook to receive real-time notifications about events. - tags: - - Webhooks - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for webhook_register - required: true - content: - application/json: - example: - tool: webhook_register - arguments: - endpoint: - url: https://example.com - method: POST - eventTypes: [] - schema: - type: object - properties: - tool: - type: string - enum: - - webhook_register - arguments: - $ref: '#/components/schemas/RegisterWebhookInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/WebhookRegister' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /webhook-list: - post: - operationId: webhook_list - summary: List webhooks - description: List all registered webhooks. - tags: - - Webhooks - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for webhook_list - required: true - content: - application/json: - example: - tool: webhook_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - webhook_list - arguments: - $ref: '#/components/schemas/ListWebhooksInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/WebhookList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /webhook-delete: - post: - operationId: webhook_delete - summary: Delete webhook - description: Delete a registered webhook. - tags: - - Webhooks - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for webhook_delete - required: true - content: - application/json: - example: - tool: webhook_delete - arguments: - webhookId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - webhook_delete - arguments: - $ref: '#/components/schemas/DeleteWebhookInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/WebhookDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-create: - post: - operationId: service_token_create - summary: Create service token - description: >- - Create a new service token for API authentication. Returns the full token which should be stored securely as it - cannot be retrieved later. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_create - required: true - content: - application/json: - example: - tool: service_token_create - arguments: - name: Example Name - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_create - arguments: - $ref: '#/components/schemas/CreateServiceTokenInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreateServiceTokenOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-list: - post: - operationId: service_token_list - summary: List service tokens - description: List all service tokens for the authenticated customer. Secrets are never returned, only metadata. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_list - required: true - content: - application/json: - example: - tool: service_token_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_list - arguments: - $ref: '#/components/schemas/ListServiceTokensInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/ListServiceTokensOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-get: - post: - operationId: service_token_get - summary: Get service token - description: Get detailed information about a specific service token. The secret is never returned. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_get - required: true - content: - application/json: - example: - tool: service_token_get - arguments: - id: '1234567890' - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_get - arguments: - $ref: '#/components/schemas/GetServiceTokenInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/GetServiceTokenOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-update: - post: - operationId: service_token_update - summary: Update service token - description: Update a service token. Only name, description, and expiration can be modified. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_update - required: true - content: - application/json: - example: - tool: service_token_update - arguments: - id: '1234567890' - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_update - arguments: - $ref: '#/components/schemas/UpdateServiceTokenInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/UpdateServiceTokenOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-archive: - post: - operationId: service_token_archive - summary: Archive service token - description: Archive (soft delete) a service token. This immediately invalidates the token for authentication. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_archive - required: true - content: - application/json: - example: - tool: service_token_archive - arguments: - id: '1234567890' - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_archive - arguments: - $ref: '#/components/schemas/ArchiveServiceTokenInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/ArchiveServiceTokenOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /customer-get: - post: - operationId: customer_get - summary: Get customer info - description: Get detailed information about a customer from the core database. - tags: - - Customers - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for customer_get - required: true - content: - application/json: - example: - tool: customer_get - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - customer_get - arguments: - $ref: '#/components/schemas/GetCustomerInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/GetCustomerOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /customer-get-seats: - post: - operationId: customer_get_seats - summary: Get customer seats - description: Get all seats associated with a customer from the core database. - tags: - - Customers - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for customer_get_seats - required: true - content: - application/json: - example: - tool: customer_get_seats - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - customer_get_seats - arguments: - $ref: '#/components/schemas/GetCustomerSeatsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/GetCustomerSeatsOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' -components: - schemas: - ListChannelsInput: - type: object - properties: {} - GetCustomerInput: - type: object - properties: - customerId: - description: >- - The unique identifier of the customer to retrieve. If not provided, uses the authenticated users customer - ID. - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - GetCustomerSeatsInput: - type: object - properties: - customerId: - description: >- - The unique identifier of the customer whose seats to retrieve. If not provided, uses the authenticated users - customer ID. - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - SyncSalesAgentsInput: - type: object - properties: - creativeId: - type: string - example: example_id_123 - required: - - creativeId - ListCountriesInput: - type: object - properties: {} - ListLanguagesInput: - type: object - properties: {} - CreateMediaBuyInput: - type: object - properties: - tacticId: - type: number - example: 100 - agentId: - type: string - example: example_id_123 - name: - type: string - minLength: 1 - example: Example Name - description: - type: string - example: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - budgetAmount: - type: number - minimum: 0 - exclusiveMinimum: true - budgetCurrency: - type: string - pricingCpm: - type: number - minimum: 0 - exclusiveMinimum: true - pricingSignalCost: - type: number - displayOrder: - type: integer - minimum: -9007199254740991 - maximum: 9007199254740991 - creatives: - type: array - items: - type: object - properties: - creative_id: - type: string - name: - type: string - format_id: - anyOf: - - type: string - - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - assets: - type: object - additionalProperties: - type: object - properties: - url: - type: string - width: - type: number - height: - type: number - required: - - url - click_url: - type: string - required: - - creative_id - - name - - format_id - required: - - mediaProductId - - budgetAmount - example: [] - creatives: - type: array - items: - type: object - properties: - creative_id: - type: string - name: - type: string - format_id: - anyOf: - - type: string - - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - assets: - type: object - additionalProperties: - type: object - properties: - url: - type: string - width: - type: number - height: - type: number - required: - - url - click_url: - type: string - required: - - creative_id - - name - - format_id - example: [] - required: - - tacticId - - agentId - - name - - products - UpdateMediaBuyInput: - type: object - properties: - mediaBuyId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - description: - type: string - example: string - status: - type: string - enum: - - DRAFT - - PENDING_APPROVAL - - ACTIVE - - PAUSED - - COMPLETED - - FAILED - - REJECTED - example: DRAFT - creativeIds: - type: array - items: - type: string - example: [] - packages: - type: array - items: - type: object - properties: - packageId: - type: string - creativeIds: - type: array - items: - type: string - required: - - packageId - - creativeIds - example: [] - required: - - mediaBuyId - DeleteMediaBuyInput: - type: object - properties: - mediaBuyId: - type: string - example: example_id_123 - confirm: - type: boolean - example: true - required: - - mediaBuyId - - confirm - ExecuteMediaBuyInput: - type: object - properties: - mediaBuyId: - type: string - example: example_id_123 - required: - - mediaBuyId - GetMediaBuyInput: - type: object - properties: - mediaBuyId: - type: string - example: example_id_123 - required: - - mediaBuyId - ListMediaBuysInput: - type: object - properties: - tacticId: - type: number - example: 100 - status: - type: string - enum: - - DRAFT - - PENDING_APPROVAL - - ACTIVE - - PAUSED - - COMPLETED - - FAILED - - REJECTED - example: DRAFT - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - ValidateMediaBuyBudgetInput: - type: object - properties: - tacticId: - type: number - example: 100 - newBudgetAmount: - type: number - minimum: 0 - exclusiveMinimum: true - example: 100 - required: - - tacticId - - newBudgetAmount - ListNotificationsInput: - type: object - properties: - brandAgentId: - type: number - example: 100 - campaignId: - type: string - example: example_id_123 - creativeId: - type: string - example: example_id_123 - tacticId: - type: string - example: example_id_123 - types: - type: array - items: - type: string - example: [] - unreadOnly: - type: boolean - example: true - limit: - type: number - example: 100 - offset: - type: number - example: 100 - MarkNotificationReadInput: - type: object - properties: - notificationId: - type: string - example: example_id_123 - required: - - notificationId - MarkNotificationAcknowledgedInput: - type: object - properties: - notificationId: - type: string - example: example_id_123 - required: - - notificationId - MarkAllNotificationsReadInput: - type: object - properties: {} - DiscoverProductsInput: - type: object - properties: - brief: - description: >- - Natural language description of campaign requirements (e.g., "Launch $50k luxury electric vehicle awareness - campaign targeting 10M affluent buyers, 60 days, max CPM $15") - type: string - minLength: 1 - example: string - brandManifestUrl: - description: Valid URL for the brand (e.g., company website https://example.com or hosted brand manifest JSON) - type: string - format: uri - example: https://example.com - filters: - description: Structured filters for product discovery - type: object - properties: - deliveryType: - type: string - enum: - - guaranteed - - non_guaranteed - isFixedPrice: - description: Filter for fixed price vs auction products - type: boolean - formatTypes: - description: Filter by format types - type: array - items: - type: string - enum: - - video - - display - - audio - standardFormatsOnly: - description: Only return products accepting IAB standard formats - type: boolean - minExposures: - description: Minimum exposures/impressions needed for measurement validity - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - agentId: - description: 'Optional: Query a specific sales agent by ID. If not provided, queries all active sales agents.' - type: string - example: example_id_123 - saveToDatabase: - description: 'Whether to save discovered products for future use (default: true)' - type: boolean - example: true - required: - - brief - - brandManifestUrl - SaveProductInput: - type: object - properties: - productId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - description: - type: string - example: string - publisherId: - type: string - example: example_id_123 - publisherName: - type: string - example: Example Name - deliveryType: - type: string - enum: - - guaranteed - - non_guaranteed - example: guaranteed - inventoryType: - type: string - enum: - - premium - - run_of_site - - targeted_package - example: premium - creativeFormats: - anyOf: - - type: array - items: - type: string - - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - pricingModel: - type: string - enum: - - auction - - fixed_cpm - example: auction - fixedCpm: - type: number - minimum: 0 - exclusiveMinimum: true - example: 100 - floorCpm: - type: number - minimum: 0 - exclusiveMinimum: true - example: 100 - targetCpm: - type: number - minimum: 0 - exclusiveMinimum: true - example: 100 - pricingOptions: - type: array - items: - type: object - additionalProperties: {} - example: [] - supportedTargeting: - type: array - items: - type: string - example: [] - adcpAgentId: - type: string - example: example_id_123 - required: - - productId - - name - - description - - publisherId - - publisherName - - deliveryType - - inventoryType - - pricingModel - ListProductsInput: - type: object - properties: - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - SyncProductsInput: - type: object - properties: - sourceId: - type: string - example: example_id_123 - required: - - sourceId - GetAgentInput: - type: object - properties: - agentId: - description: The agent ID to retrieve - type: string - example: example_id_123 - required: - - agentId - ListAgentsInput: - type: object - properties: - type: - description: Filter by agent type (SALES or OUTCOME) - type: string - enum: - - SALES - - OUTCOME - example: SALES - status: - description: Filter by status (PENDING, ACTIVE, DISABLED) - type: string - enum: - - PENDING - - ACTIVE - - DISABLED - example: PENDING - organizationId: - description: Filter by organization ID - type: string - example: example_id_123 - relationship: - description: >- - Filter by relationship (SELF = owned by you, SCOPE3 = Scope3-provided, MARKETPLACE = third-party marketplace - agents) - type: string - enum: - - SELF - - SCOPE3 - - MARKETPLACE - example: SELF - name: - description: Filter by agent name (partial match) - type: string - example: Example Name - RegisterAgentInput: - type: object - properties: - type: - description: The type of agent to register - type: string - enum: - - SALES - - OUTCOME - example: SALES - name: - description: Agent name - type: string - minLength: 1 - example: Example Name - description: - description: Agent description - type: string - example: string - endpointUrl: - description: Agent endpoint URL - type: string - format: uri - example: https://example.com - protocol: - description: Protocol used by the agent (MCP or A2A) - type: string - enum: - - MCP - - A2A - example: MCP - authenticationType: - description: Authentication type - type: string - enum: - - API_KEY - - OAUTH - - NO_AUTH - - JWT - example: API_KEY - organizationId: - description: Organization ID - type: string - example: example_id_123 - auth: - description: Authentication configuration object - anyOf: - - type: object - properties: - type: - type: string - enum: - - jwt - privateKey: - type: string - minLength: 1 - issuer: - type: string - minLength: 1 - subject: - type: string - minLength: 1 - keyId: - type: string - minLength: 1 - scope: - type: string - minLength: 1 - tokenEndpointUrl: - type: string - format: uri - audienceUrl: - type: string - format: uri - algorithm: - type: string - enum: - - ES256 - - RS256 - environment: - type: string - required: - - type - - privateKey - - issuer - - subject - - keyId - - scope - - tokenEndpointUrl - - audienceUrl - - type: object - properties: - type: - type: string - enum: - - bearer - - apikey - - api_key - token: - type: string - minLength: 1 - required: - - type - - token - - type: object - properties: - type: - type: string - enum: - - oauth - - oauth2 - token: - type: string - minLength: 1 - required: - - type - - token - - type: object - properties: {} - required: - - type - - name - - endpointUrl - - protocol - UnregisterAgentInput: - type: object - properties: - agentId: - description: The agent ID to unregister - type: string - example: example_id_123 - required: - - agentId - UpdateAgentInput: - type: object - properties: - agentId: - description: The agent ID to update - type: string - example: example_id_123 - name: - description: New agent name - type: string - example: Example Name - description: - description: New agent description - type: string - example: string - endpointUrl: - description: New endpoint URL - type: string - format: uri - example: https://example.com - protocol: - description: New protocol - type: string - enum: - - MCP - - A2A - example: MCP - authenticationType: - description: New authentication type - type: string - enum: - - API_KEY - - OAUTH - - NO_AUTH - - JWT - example: API_KEY - auth: - description: New authentication configuration - anyOf: - - type: object - properties: - type: - type: string - enum: - - jwt - privateKey: - type: string - minLength: 1 - issuer: - type: string - minLength: 1 - subject: - type: string - minLength: 1 - keyId: - type: string - minLength: 1 - scope: - type: string - minLength: 1 - tokenEndpointUrl: - type: string - format: uri - audienceUrl: - type: string - format: uri - algorithm: - type: string - enum: - - ES256 - - RS256 - environment: - type: string - required: - - type - - privateKey - - issuer - - subject - - keyId - - scope - - tokenEndpointUrl - - audienceUrl - - type: object - properties: - type: - type: string - enum: - - bearer - - apikey - - api_key - token: - type: string - minLength: 1 - required: - - type - - token - - type: object - properties: - type: - type: string - enum: - - oauth - - oauth2 - token: - type: string - minLength: 1 - required: - - type - - token - - type: object - properties: {} - required: - - agentId - CreateTacticInput: - type: object - properties: - campaignId: - type: string - example: example_id_123 - name: - type: string - minLength: 1 - example: Example Name - prompt: - type: string - example: string - channelCodes: - type: array - items: - type: string - enum: - - ctv - - video - - display - - app - - social - example: [] - countryCodes: - type: array - items: - type: string - example: [] - languages: - description: Language codes - type: array - items: - type: string - example: [] - availableBrandStandards: - type: array - items: - type: object - properties: - id: - type: number - name: - type: string - required: - - id - - name - example: [] - availableBrandStory: - type: array - items: - type: object - properties: - id: - type: number - name: - type: string - required: - - id - - name - example: [] - required: - - campaignId - - name - UpdateTacticInput: - type: object - properties: - tacticId: - type: number - example: 100 - name: - type: string - example: Example Name - prompt: - type: string - example: string - channelCodes: - type: array - items: - type: string - enum: - - ctv - - video - - display - - app - - social - example: [] - countryCodes: - type: array - items: - type: string - example: [] - availableBrandStandards: - type: array - items: - type: object - properties: - id: - type: number - name: - type: string - required: - - id - - name - example: [] - availableBrandStory: - type: array - items: - type: object - properties: - id: - type: number - name: - type: string - required: - - id - - name - example: [] - required: - - tacticId - DeleteTacticInput: - type: object - properties: - tacticId: - type: number - example: 100 - confirm: - type: boolean - example: true - required: - - tacticId - - confirm - GetTacticInput: - type: object - properties: - tacticId: - type: number - example: 100 - required: - - tacticId - ListTacticsInput: - type: object - properties: - campaignId: - type: string - example: example_id_123 - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - LinkCampaignToTacticInput: - type: object - properties: - tacticId: - type: number - example: 100 - campaignId: - type: string - example: example_id_123 - required: - - tacticId - - campaignId - UnlinkCampaignFromTacticInput: - type: object - properties: - tacticId: - type: number - example: 100 - campaignId: - type: string - example: example_id_123 - required: - - tacticId - - campaignId - RegisterWebhookInput: - type: object - properties: - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - endpoint: - type: object - properties: - url: - type: string - format: uri - method: - type: string - enum: - - POST - - PUT - headers: - type: object - additionalProperties: - type: string - authentication: - type: object - properties: - type: - type: string - enum: - - bearer - - basic - - hmac - credentials: - type: string - required: - - type - - credentials - required: - - url - - method - eventTypes: - type: array - items: - type: string - example: [] - filters: - type: object - properties: - campaigns: - type: array - items: - type: string - tactics: - type: array - items: - type: string - creatives: - type: array - items: - type: string - mediaBuys: - type: array - items: - type: string - metrics: - type: array - items: - type: string - minSeverity: - type: string - enum: - - info - - warning - - critical - retryPolicy: - type: object - properties: - maxRetries: - type: integer - minimum: 0 - maximum: 9007199254740991 - backoffMultiplier: - type: number - minimum: 0 - exclusiveMinimum: true - maxBackoffSeconds: - type: number - minimum: 0 - exclusiveMinimum: true - required: - - endpoint - - eventTypes - ListWebhooksInput: - type: object - properties: - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - DeleteWebhookInput: - type: object - properties: - webhookId: - type: string - example: example_id_123 - required: - - webhookId - CreateServiceTokenInput: - type: object - properties: - name: - description: Human-readable name for the service token - type: string - minLength: 1 - example: Example Name - description: - description: Optional description of the token purpose and usage - type: string - example: string - expiresInDays: - description: Number of days until token expiration (max 365). If not provided, token does not expire - type: integer - exclusiveMinimum: true - maximum: 365 - example: 100 - scope: - description: 'Token scope: CUSTOMER (full customer access) or SEAT (scoped to specific seat)' - default: CUSTOMER - type: string - enum: - - CUSTOMER - - SEAT - seatName: - description: Seat name (required when scope is SEAT). The seat will be looked up for the customer. - type: string - minLength: 1 - example: Example Name - required: - - name - UpdateServiceTokenInput: - type: object - properties: - id: - description: The unique identifier of the service token to update - type: integer - format: int64 - example: 100 - name: - description: Updated human-readable name for the service token - type: string - minLength: 1 - example: Example Name - description: - description: Updated description of the token purpose and usage - type: string - example: string - expiresInDays: - description: Number of days to extend expiration from now (max 365). Updates the expiresAt timestamp - type: integer - exclusiveMinimum: true - maximum: 365 - example: 100 - required: - - id - ArchiveServiceTokenInput: - type: object - properties: - id: - description: The unique identifier of the service token to archive - type: integer - format: int64 - example: 100 - required: - - id - GetServiceTokenInput: - type: object - properties: - id: - description: The unique identifier of the service token to retrieve - type: integer - format: int64 - example: 100 - includeSecret: - description: Whether to fetch the access_client_secret from Google Secret Manager. Defaults to false for security - default: false - type: boolean - required: - - id - ListServiceTokensInput: - type: object - properties: - includeArchived: - description: Whether to include archived tokens in the response - default: false - type: boolean - seatId: - description: Filter tokens by seat ID - type: integer - format: int64 - example: 100 - userId: - description: Filter tokens by user ID - type: integer - format: int64 - example: 100 - MediaBuyGet: - type: object - properties: - id: - type: string - example: example_id_123 - tacticId: - type: number - example: 100 - customerId: - type: number - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - required: - - mediaProductId - - salesAgentId - example: [] - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - example: [] - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - example: [] - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - status: - type: string - example: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - TacticGet: - type: object - properties: - id: - type: number - example: 100 - name: - type: string - example: Example Name - prompt: - type: string - example: string - campaignIds: - type: array - items: - type: string - example: [] - channelCodes: - type: array - items: - type: string - example: [] - countryCodes: - type: array - items: - type: string - example: [] - mediaBuyCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - channelCodes - - countryCodes - - createdAt - - updatedAt - MCPContent: - type: object - properties: - type: - type: string - enum: - - text - example: text - text: - type: string - example: string - required: - - type - - text - additionalProperties: false - BadRequest: - description: Bad request error response - type: object - properties: - error: - type: string - example: string - message: - type: string - example: string - required: - - error - additionalProperties: false - Unauthorized: - description: Unauthorized error response - type: object - properties: - error: - type: string - example: string - message: - type: string - example: string - required: - - error - additionalProperties: false - InternalError: - description: Internal server error response - type: object - properties: - error: - type: string - example: string - message: - type: string - example: string - required: - - error - additionalProperties: false - ChannelList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - channel: - type: string - displayName: - type: string - required: - - channel - - displayName - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - GetCustomerOutput: - type: object - properties: - id: - description: Unique identifier for the customer - type: number - example: 100 - company: - description: Company name - type: string - example: string - name: - description: Customer display name - type: string - example: Example Name - active: - description: Whether the customer is currently active - type: boolean - example: true - createdAt: - description: ISO 8601 timestamp when the customer was created - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - company - - name - - active - - createdAt - additionalProperties: false - GetCustomerSeatsOutput: - type: object - properties: - customerId: - description: The customer ID these seats belong to - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - seats: - description: Array of seats belonging to the customer - type: array - items: - type: object - properties: - id: - description: Unique identifier for the seat - type: string - name: - description: Seat display name - type: string - customerId: - description: Customer ID that owns this seat - type: number - active: - description: Whether the seat is currently active - type: boolean - required: - - id - - name - - customerId - - active - additionalProperties: false - example: [] - count: - description: Total number of seats returned - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - customerId - - seats - - count - additionalProperties: false - CreativeSyncSalesAgents: - type: object - properties: - success: - type: boolean - example: true - creativeId: - type: string - example: example_id_123 - campaignId: - type: string - example: example_id_123 - required: - - success - - creativeId - additionalProperties: false - CountryList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - key: - type: string - displayName: - type: string - required: - - key - - displayName - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - LanguageList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - key: - type: string - displayName: - type: string - required: - - key - - displayName - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - MediaBuyDelete: - type: object - properties: - success: - type: boolean - example: true - id: - type: string - example: example_id_123 - required: - - success - - id - additionalProperties: false - MediaBuyExecute: - type: object - properties: - success: - type: boolean - example: true - mediaBuyId: - type: string - example: example_id_123 - status: - type: string - example: string - adcpMediaBuyId: - type: string - example: example_id_123 - adcpStatus: - type: string - example: string - required: - - success - - mediaBuyId - - status - additionalProperties: false - MediaBuyList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - $ref: '#/components/schemas/MediaBuyGetOutput' - example: [] - required: - - total - - items - additionalProperties: false - MediaBuyValidateBudget: - type: object - properties: - valid: - type: boolean - example: true - message: - type: string - example: string - required: - - valid - additionalProperties: false - NotificationsList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - hasMore: - type: boolean - example: true - items: - type: array - items: - type: object - properties: - id: - type: string - type: - type: string - data: - type: object - additionalProperties: {} - read: - type: boolean - acknowledged: - type: boolean - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - type - - data - - read - - acknowledged - - createdAt - additionalProperties: false - example: [] - required: - - total - - hasMore - - items - additionalProperties: false - NotificationsMarkRead: - type: object - properties: - success: - type: boolean - example: true - notificationId: - type: string - example: example_id_123 - required: - - success - - notificationId - additionalProperties: false - NotificationsMarkAcknowledged: - type: object - properties: - success: - type: boolean - example: true - notificationId: - type: string - example: example_id_123 - required: - - success - - notificationId - additionalProperties: false - NotificationsMarkAllRead: - type: object - properties: - success: - type: boolean - example: true - count: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - success - - count - additionalProperties: false - MediaProductDiscover: - type: object - properties: - success: - type: boolean - example: true - productsFound: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - productsSaved: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - successfulAgents: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - failedAgents: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - products: - type: array - items: - type: object - properties: - productId: - type: string - name: - type: string - publisherName: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - deliveryType: - type: string - enum: - - guaranteed - - non_guaranteed - inventoryType: - type: string - enum: - - premium - - run_of_site - - targeted_package - creativeFormats: - anyOf: - - type: array - items: - type: string - - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - fixedCpm: - type: number - floorCpm: - type: number - targetCpm: - type: number - required: - - productId - - name - - publisherName - - deliveryType - - inventoryType - additionalProperties: false - example: [] - required: - - success - - productsFound - - productsSaved - - successfulAgents - - failedAgents - - products - additionalProperties: false - MediaProductSave: - type: object - properties: - id: - type: string - example: example_id_123 - productId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - publisherId: - type: string - example: example_id_123 - publisherName: - type: string - example: Example Name - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - productId - - name - - publisherId - - publisherName - - customerId - - createdAt - - updatedAt - additionalProperties: false - MediaProductList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - id: - type: string - productId: - type: string - name: - type: string - salesAgent: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - deliveryType: - type: string - enum: - - guaranteed - - non_guaranteed - format: - type: string - creativeFormats: - anyOf: - - type: array - items: - type: string - - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - id - - productId - - name - - deliveryType - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - MediaProductSync: - type: object - properties: - success: - type: boolean - example: true - productsSaved: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - success - - productsSaved - additionalProperties: false - AgentGet: - anyOf: - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - authenticationType: - type: string - description: - type: string - organizationId: - type: string - registeredBy: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - - authenticationType - - createdAt - - updatedAt - additionalProperties: false - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - authenticationType: - type: string - description: - type: string - organizationId: - type: string - registeredBy: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - customerAccountCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - - authenticationType - - createdAt - - updatedAt - - customerAccountCount - additionalProperties: false - AgentList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - anyOf: - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - additionalProperties: false - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - customerAccountCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - - customerAccountCount - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - AgentRegister: - type: object - properties: - agentId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - type: - type: string - enum: - - SALES - - OUTCOME - example: SALES - status: - type: string - example: string - endpointUrl: - type: string - example: https://example.com - required: - - agentId - - name - - type - - status - - endpointUrl - additionalProperties: false - AgentUnregister: - type: object - properties: - success: - type: boolean - example: true - agentId: - type: string - example: example_id_123 - type: - type: string - enum: - - SALES - - OUTCOME - example: SALES - required: - - success - - agentId - - type - additionalProperties: false - AgentUpdate: - type: object - properties: - agentId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - type: - type: string - enum: - - SALES - - OUTCOME - example: SALES - status: - type: string - example: string - required: - - agentId - - name - - type - - status - additionalProperties: false - TacticCreate: - type: object - properties: - id: - type: number - example: 100 - name: - type: string - example: Example Name - prompt: - type: string - example: string - campaignId: - type: string - example: example_id_123 - channelCodes: - type: array - items: - type: string - example: [] - countryCodes: - type: array - items: - type: string - example: [] - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - campaignId - - channelCodes - - countryCodes - - createdAt - additionalProperties: false - TacticDelete: - type: object - properties: - success: - type: boolean - example: true - tacticId: - type: number - example: 100 - required: - - success - - tacticId - additionalProperties: false - TacticList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - $ref: '#/components/schemas/TacticGetOutput' - example: [] - required: - - total - - items - additionalProperties: false - TacticLinkCampaign: - type: object - properties: - success: - type: boolean - example: true - tacticId: - type: number - example: 100 - campaignId: - type: string - example: example_id_123 - required: - - success - - tacticId - - campaignId - additionalProperties: false - TacticUnlinkCampaign: - type: object - properties: - success: - type: boolean - example: true - tacticId: - type: number - example: 100 - campaignId: - type: string - example: example_id_123 - required: - - success - - tacticId - - campaignId - additionalProperties: false - WebhookRegister: - type: object - properties: - id: - type: string - example: example_id_123 - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - endpoint: - type: object - properties: - url: - type: string - method: - type: string - authenticationType: - type: string - required: - - url - - method - additionalProperties: false - eventTypes: - type: array - items: - type: string - example: [] - filters: - type: object - properties: - campaigns: - type: array - items: - type: string - tactics: - type: array - items: - type: string - creatives: - type: array - items: - type: string - mediaBuys: - type: array - items: - type: string - metrics: - type: array - items: - type: string - minSeverity: - type: string - additionalProperties: false - retryPolicy: - type: object - properties: - maxRetries: - type: integer - minimum: 0 - maximum: 9007199254740991 - backoffMultiplier: - type: number - minimum: 0 - exclusiveMinimum: true - maxBackoffSeconds: - type: number - minimum: 0 - exclusiveMinimum: true - required: - - maxRetries - - backoffMultiplier - - maxBackoffSeconds - additionalProperties: false - status: - type: string - example: string - testResult: - type: object - properties: - success: - type: boolean - statusCode: - type: integer - minimum: -9007199254740991 - maximum: 9007199254740991 - error: - type: string - required: - - success - additionalProperties: false - required: - - id - - endpoint - - eventTypes - - retryPolicy - - status - - testResult - additionalProperties: false - WebhookList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - id: - type: string - status: - type: string - endpoint: - type: object - properties: - url: - type: string - method: - type: string - authenticationType: - type: string - required: - - url - - method - additionalProperties: false - eventTypes: - type: array - items: - type: string - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - failureCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - lastSuccess: - nullable: true - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - lastFailure: - nullable: true - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - status - - endpoint - - eventTypes - - failureCount - - createdAt - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - WebhookDelete: - type: object - properties: - success: - type: boolean - example: true - webhookId: - type: string - example: example_id_123 - required: - - success - - webhookId - additionalProperties: false - CreateServiceTokenOutput: - type: object - properties: - id: - description: Unique identifier for the service token - type: integer - format: int64 - example: 100 - customerId: - description: Customer ID that owns this token - type: number - example: 100 - seatId: - description: Seat ID if token is scoped to a specific seat - type: integer - format: int64 - example: 100 - userId: - description: User ID if token is scoped to a specific user - type: integer - format: int64 - example: 100 - organizationId: - description: Optional organization identifier for scoping the token - type: string - example: example_id_123 - name: - description: Human-readable name of the token - type: string - example: Example Name - description: - description: Description of the token purpose - type: string - example: string - accessClientId: - description: The public client ID portion of the token credentials (safe to log) - type: string - example: example_id_123 - accessClientSecret: - description: The secret portion of the token credentials. ONLY returned on creation, never retrievable again! - type: string - example: string - expiresAt: - description: ISO 8601 timestamp when the token expires, if set - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - description: ISO 8601 timestamp when the token was created - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - customerId - - name - - accessClientId - - accessClientSecret - - createdAt - additionalProperties: false - UpdateServiceTokenOutput: - type: object - properties: - id: - description: Unique identifier for the service token - type: integer - format: int64 - example: 100 - name: - description: Updated human-readable name of the token - type: string - example: Example Name - description: - description: Updated description of the token purpose - type: string - example: string - expiresAt: - description: ISO 8601 timestamp when the token expires, if updated - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - description: ISO 8601 timestamp when the token was last updated - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - updatedAt - additionalProperties: false - ArchiveServiceTokenOutput: - type: object - properties: - id: - description: Unique identifier for the archived token - type: integer - format: int64 - example: 100 - archivedAt: - description: ISO 8601 timestamp when the token was archived - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - archivedAt - additionalProperties: false - GetServiceTokenOutput: - type: object - properties: - id: - description: Unique identifier for the service token - type: integer - format: int64 - example: 100 - customerId: - description: Customer ID that owns this token - type: number - example: 100 - seatId: - description: Seat ID if token is scoped to a specific seat - type: integer - format: int64 - example: 100 - userId: - description: User ID if token is scoped to a specific user - type: integer - format: int64 - example: 100 - organizationId: - description: Optional organization identifier for scoping the token - type: string - example: example_id_123 - name: - description: Human-readable name of the token - type: string - example: Example Name - description: - description: Description of the token purpose - type: string - example: string - accessClientId: - description: The public client ID portion of the token credentials (safe to log) - type: string - example: example_id_123 - accessClientSecret: - description: The secret portion of the token credentials. Only included if includeSecret=true was passed - type: string - example: string - expiresAt: - description: ISO 8601 timestamp when the token expires, if set - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - description: ISO 8601 timestamp when the token was created - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - description: ISO 8601 timestamp when the token was last updated - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - archivedAt: - description: ISO 8601 timestamp when the token was archived, if archived - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - customerId - - name - - accessClientId - - createdAt - - updatedAt - additionalProperties: false - ListServiceTokensOutput: - type: object - properties: - tokens: - description: 'Array of service tokens. Note: accessClientSecret is never included in list responses' - type: array - items: - type: object - properties: - id: - description: Unique identifier for the service token - type: integer - format: int64 - customerId: - description: Customer ID that owns this token - type: number - seatId: - description: Seat ID if token is scoped to a specific seat - type: integer - format: int64 - seatName: - description: Seat name if token is scoped to a specific seat - type: string - userId: - description: User ID if token is scoped to a specific user - type: integer - format: int64 - organizationId: - description: Optional organization identifier for scoping the token - type: string - name: - description: Human-readable name of the token - type: string - description: - description: Description of the token purpose - type: string - accessClientId: - description: The public client ID portion of the token credentials (safe to log) - type: string - expiresAt: - description: ISO 8601 timestamp when the token expires, if set - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - createdAt: - description: ISO 8601 timestamp when the token was created - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - description: ISO 8601 timestamp when the token was last updated - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - archivedAt: - description: ISO 8601 timestamp when the token was archived, if archived - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - customerId - - name - - accessClientId - - createdAt - - updatedAt - additionalProperties: false - example: [] - count: - description: Total number of tokens returned - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - tokens - - count - additionalProperties: false - MediaBuyGetOutput: - type: object - properties: - id: - type: string - example: example_id_123 - tacticId: - type: number - example: 100 - customerId: - type: number - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - mediaProductId - - salesAgentId - additionalProperties: false - example: [] - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - additionalProperties: false - example: [] - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - example: [] - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - additionalProperties: false - status: - type: string - example: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - additionalProperties: false - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - additionalProperties: false - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - additionalProperties: false - TacticGetOutput: - type: object - properties: - id: - type: number - example: 100 - name: - type: string - example: Example Name - prompt: - type: string - example: string - campaignIds: - type: array - items: - type: string - example: [] - channelCodes: - type: array - items: - type: string - example: [] - countryCodes: - type: array - items: - type: string - example: [] - mediaBuyCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - channelCodes - - countryCodes - - createdAt - - updatedAt - additionalProperties: false - MediaBuyCreate: - type: object - properties: - id: - type: string - example: example_id_123 - tacticId: - type: number - example: 100 - customerId: - type: number - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - mediaProductId - - salesAgentId - additionalProperties: false - example: [] - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - additionalProperties: false - example: [] - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - example: [] - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - additionalProperties: false - status: - type: string - example: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - additionalProperties: false - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - additionalProperties: false - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - additionalProperties: false - MediaBuyUpdate: - type: object - properties: - id: - type: string - example: example_id_123 - tacticId: - type: number - example: 100 - customerId: - type: number - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - mediaProductId - - salesAgentId - additionalProperties: false - example: [] - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - additionalProperties: false - example: [] - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - example: [] - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - additionalProperties: false - status: - type: string - example: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - additionalProperties: false - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - additionalProperties: false - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - additionalProperties: false - TacticUpdate: - type: object - properties: - id: - type: number - example: 100 - name: - type: string - example: Example Name - prompt: - type: string - example: string - campaignIds: - type: array - items: - type: string - example: [] - channelCodes: - type: array - items: - type: string - example: [] - countryCodes: - type: array - items: - type: string - example: [] - mediaBuyCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - channelCodes - - countryCodes - - createdAt - - updatedAt - additionalProperties: false - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT diff --git a/platform-api.yaml b/platform-api.yaml deleted file mode 100644 index 5dabd8b..0000000 --- a/platform-api.yaml +++ /dev/null @@ -1,7516 +0,0 @@ -# This OpenAPI specification is auto-generated from TypeScript Schemas -# DO NOT EDIT THIS FILE MANUALLY -# API Type: BUYER - -openapi: 3.0.0 -info: - title: Scope3 Platform API - version: 1.0.0 - description: |- - API for brand advertisers to manage brand agents, campaigns, creatives, and discover marketplace offerings. - - This API provides buyers with tools to: - - Manage brand agents and campaign briefs - - Create and manage creatives - - Discover and save media products from the marketplace - - View campaigns, tactics, and media buys (read-only) - - Configure brand standards and brand stories -servers: - - url: https://api.agentic.scope3.com/mcp - description: Production server - - url: https://api.agentic.staging.scope3.com/mcp - description: Staging server -paths: - /mcp-initialize: - post: - operationId: mcp_initialize - summary: Initialize MCP session - description: >- - Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as - a UUID and included in the mcp-session-id header for all subsequent requests. - tags: - - MCP - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: MCP session identifier (UUID). Generate a new UUID for session initialization. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - jsonrpc: - type: string - enum: - - '2.0' - id: - oneOf: - - type: string - - type: number - method: - type: string - enum: - - initialize - params: - type: object - properties: - protocolVersion: - type: string - example: '2024-11-05' - capabilities: - type: object - clientInfo: - type: object - properties: - name: - type: string - version: - type: string - required: - - name - - version - required: - - protocolVersion - - capabilities - - clientInfo - required: - - jsonrpc - - id - - method - - params - responses: - '200': - description: Session initialized successfully - content: - application/json: - schema: - type: object - properties: - jsonrpc: - type: string - enum: - - '2.0' - id: - oneOf: - - type: string - - type: number - result: - type: object - properties: - protocolVersion: - type: string - capabilities: - type: object - serverInfo: - type: object - properties: - name: - type: string - version: - type: string - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - /brand-agent-list: - post: - operationId: brand_agent_list - summary: List brand agents - description: >- - List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no - parameters required. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_agent_list - required: true - content: - application/json: - example: - tool: brand_agent_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_list - arguments: - $ref: '#/components/schemas/ListBrandAgentsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-agent-get: - post: - operationId: brand_agent_get - summary: Get brand agent - description: Get detailed information about a specific brand agent (advertiser account) by ID. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_agent_get - required: true - content: - application/json: - example: - tool: brand_agent_get - arguments: - brandAgentId: 100 - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_get - arguments: - $ref: '#/components/schemas/GetBrandAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-agent-create: - post: - operationId: brand_agent_create - summary: Create brand agent - description: >- - Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, - creatives, audiences, standards, and measurement sources. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_agent_create - required: true - content: - application/json: - example: - tool: brand_agent_create - arguments: - name: Example Name - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_create - arguments: - $ref: '#/components/schemas/CreateBrandAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-agent-update: - post: - operationId: brand_agent_update - summary: Update brand agent - description: Update an existing brand agent with new information. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_agent_update - required: true - content: - application/json: - example: - tool: brand_agent_update - arguments: - brandAgentId: 100 - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_update - arguments: - $ref: '#/components/schemas/UpdateBrandAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-agent-delete: - post: - operationId: brand_agent_delete - summary: Delete brand agent - description: Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. - tags: - - Brand Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_agent_delete - required: true - content: - application/json: - example: - tool: brand_agent_delete - arguments: - brandAgentId: 100 - schema: - type: object - properties: - tool: - type: string - enum: - - brand_agent_delete - arguments: - $ref: '#/components/schemas/DeleteBrandAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandAgentDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-list: - post: - operationId: campaign_list - summary: List campaigns - description: List all campaigns with optional filtering by brand agent. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for campaign_list - required: true - content: - application/json: - example: - tool: campaign_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_list - arguments: - $ref: '#/components/schemas/ListCampaignsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-create: - post: - operationId: campaign_create - summary: Create campaign - description: >- - Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, - budget, and creative requirements. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for campaign_create - required: true - content: - application/json: - example: - tool: campaign_create - arguments: - brandAgentId: 100 - prompt: string - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_create - arguments: - $ref: '#/components/schemas/CreateCampaignInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-get: - post: - operationId: campaign_get - summary: Get campaign - description: Get detailed information about a specific campaign. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for campaign_get - required: true - content: - application/json: - example: - tool: campaign_get - arguments: - campaignId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_get - arguments: - $ref: '#/components/schemas/GetCampaignInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-update: - post: - operationId: campaign_update - summary: Update campaign - description: Update an existing campaign with new information. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for campaign_update - required: true - content: - application/json: - example: - tool: campaign_update - arguments: - campaignId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_update - arguments: - $ref: '#/components/schemas/UpdateCampaignInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignUpdateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-delete: - post: - operationId: campaign_delete - summary: Delete campaign - description: Delete a campaign and all associated resources. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for campaign_delete - required: true - content: - application/json: - example: - tool: campaign_delete - arguments: - campaignId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_delete - arguments: - $ref: '#/components/schemas/DeleteCampaignInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-get-summary: - post: - operationId: campaign_get_summary - summary: Get campaign summary - description: Get a high-level summary of a campaign including key metrics and status. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for campaign_get_summary - required: true - content: - application/json: - example: - tool: campaign_get_summary - arguments: - campaignId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_get_summary - arguments: - $ref: '#/components/schemas/GetCampaignSummaryInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignGetSummary' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-list-tactics: - post: - operationId: campaign_list_tactics - summary: List campaign tactics - description: List all tactics associated with a specific campaign. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for campaign_list_tactics - required: true - content: - application/json: - example: - tool: campaign_list_tactics - arguments: - campaignId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_list_tactics - arguments: - $ref: '#/components/schemas/ListCampaignTacticsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignListTactics' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /campaign-validate-brief: - post: - operationId: campaign_validate_brief - summary: Validate campaign brief - description: Validate a campaign brief to ensure it contains all necessary information for campaign creation. - tags: - - Campaigns - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for campaign_validate_brief - required: true - content: - application/json: - example: - tool: campaign_validate_brief - arguments: - brief: string - schema: - type: object - properties: - tool: - type: string - enum: - - campaign_validate_brief - arguments: - $ref: '#/components/schemas/ValidateBriefInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CampaignValidateBrief' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /asset-list: - post: - operationId: asset_list - summary: List assets - description: List all uploaded assets with optional filtering by brand agent. - tags: - - Assets - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for asset_list - required: true - content: - application/json: - example: - tool: asset_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - asset_list - arguments: - $ref: '#/components/schemas/ListAssetsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AssetList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-standards-create: - post: - operationId: brand_standards_create - summary: Create brand standards - description: >- - Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand - agent. - tags: - - Brand Standards - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_standards_create - required: true - content: - application/json: - example: - tool: brand_standards_create - arguments: - brandAgentId: 100 - prompt: string - schema: - type: object - properties: - tool: - type: string - enum: - - brand_standards_create - arguments: - $ref: '#/components/schemas/CreateBrandStandardInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStandardsCreateOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-standards-delete: - post: - operationId: brand_standards_delete - summary: Delete brand standards - description: Delete brand standards for a brand agent. - tags: - - Brand Standards - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_standards_delete - required: true - content: - application/json: - example: - tool: brand_standards_delete - arguments: - brandStandardId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - brand_standards_delete - arguments: - $ref: '#/components/schemas/DeleteBrandStandardInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStandardsDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-standards-list: - post: - operationId: brand_standards_list - summary: List brand standards - description: List all brand standards with optional filtering by brand agent. - tags: - - Brand Standards - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_standards_list - required: true - content: - application/json: - example: - tool: brand_standards_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - brand_standards_list - arguments: - $ref: '#/components/schemas/ListBrandStandardsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStandardsList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-story-create: - post: - operationId: brand_story_create - summary: Create brand story - description: Create a brand story containing the narrative, history, values, and key messaging for a brand agent. - tags: - - Brand Stories - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_story_create - required: true - content: - application/json: - example: - tool: brand_story_create - arguments: - brandAgentId: null - name: Example Name - languages: [] - schema: - type: object - properties: - tool: - type: string - enum: - - brand_story_create - arguments: - $ref: '#/components/schemas/CreateBrandStoryInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStoryCreate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-story-update: - post: - operationId: brand_story_update - summary: Update brand story - description: Update an existing brand story with new information. - tags: - - Brand Stories - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_story_update - required: true - content: - application/json: - example: - tool: brand_story_update - arguments: - brandStoryId: example_id_123 - prompt: string - schema: - type: object - properties: - tool: - type: string - enum: - - brand_story_update - arguments: - $ref: '#/components/schemas/UpdateBrandStoryInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStoryUpdate' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-story-delete: - post: - operationId: brand_story_delete - summary: Delete brand story - description: Delete a brand story. - tags: - - Brand Stories - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_story_delete - required: true - content: - application/json: - example: - tool: brand_story_delete - arguments: - brandStoryId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - brand_story_delete - arguments: - $ref: '#/components/schemas/DeleteBrandStoryInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStoryDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /brand-story-list: - post: - operationId: brand_story_list - summary: List brand stories - description: List all brand stories with optional filtering by brand agent. - tags: - - Brand Stories - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for brand_story_list - required: true - content: - application/json: - example: - tool: brand_story_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - brand_story_list - arguments: - $ref: '#/components/schemas/ListBrandStoriesInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/BrandStoryList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /channel-list: - post: - operationId: channel_list - summary: List channels - description: List all available advertising channels and platforms. - tags: - - Channels - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for channel_list - required: true - content: - application/json: - example: - tool: channel_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - channel_list - arguments: - $ref: '#/components/schemas/ListChannelsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/ChannelList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /country-list: - post: - operationId: country_list - summary: List countries - description: Get all available countries for targeting. Use this to get valid country codes before creating brand agents. - tags: - - Targeting - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for country_list - required: true - content: - application/json: - example: - tool: country_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - country_list - arguments: - $ref: '#/components/schemas/ListCountriesInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CountryList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /language-list: - post: - operationId: language_list - summary: List languages - description: Get all available languages for targeting. Use this to get valid language codes before creating brand stories. - tags: - - Targeting - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for language_list - required: true - content: - application/json: - example: - tool: language_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - language_list - arguments: - $ref: '#/components/schemas/ListLanguagesInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/LanguageList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-assign: - post: - operationId: creative_assign - summary: Assign creative - description: Assign a creative to a tactic or media buy. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for creative_assign - required: true - content: - application/json: - example: - tool: creative_assign - arguments: - creativeId: example_id_123 - campaignId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - creative_assign - arguments: - $ref: '#/components/schemas/AssignCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeAssign' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-create: - post: - operationId: creative_create - summary: Create creative - description: Create a new creative with assets, copy, and targeting specifications. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for creative_create - required: true - content: - application/json: - example: - tool: creative_create - arguments: - brandAgentId: 100 - name: Example Name - schema: - type: object - properties: - tool: - type: string - enum: - - creative_create - arguments: - $ref: '#/components/schemas/CreateCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-update: - post: - operationId: creative_update - summary: Update creative - description: Update an existing creative with new assets, copy, or specifications. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for creative_update - required: true - content: - application/json: - example: - tool: creative_update - arguments: - creativeId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - creative_update - arguments: - $ref: '#/components/schemas/UpdateCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-delete: - post: - operationId: creative_delete - summary: Delete creative - description: Delete a creative and remove it from any associated tactics or media buys. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for creative_delete - required: true - content: - application/json: - example: - tool: creative_delete - arguments: - creativeId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - creative_delete - arguments: - $ref: '#/components/schemas/DeleteCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeDelete' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-get: - post: - operationId: creative_get - summary: Get creative - description: Get detailed information about a specific creative. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for creative_get - required: true - content: - application/json: - example: - tool: creative_get - arguments: - creativeId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - creative_get - arguments: - $ref: '#/components/schemas/GetCreativeInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /creative-list: - post: - operationId: creative_list - summary: List creatives - description: List all creatives with optional filtering by brand agent or campaign. - tags: - - Creatives - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for creative_list - required: true - content: - application/json: - example: - tool: creative_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - creative_list - arguments: - $ref: '#/components/schemas/ListCreativesInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreativeList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-get: - post: - operationId: media_buy_get - summary: Get media buy - description: Get detailed information about a specific media buy. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_buy_get - required: true - content: - application/json: - example: - tool: media_buy_get - arguments: - mediaBuyId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_get - arguments: - $ref: '#/components/schemas/GetMediaBuyInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-buy-list: - post: - operationId: media_buy_list - summary: List media buys - description: List all media buys with optional filtering by brand agent, campaign, or status. - tags: - - Media Buys - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_buy_list - required: true - content: - application/json: - example: - tool: media_buy_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - media_buy_list - arguments: - $ref: '#/components/schemas/ListMediaBuysInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaBuyList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /media-product-list: - post: - operationId: media_product_list - summary: List media products - description: List saved media products with optional filtering. - tags: - - Media Products - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for media_product_list - required: true - content: - application/json: - example: - tool: media_product_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - media_product_list - arguments: - $ref: '#/components/schemas/ListProductsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/MediaProductList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-get: - post: - operationId: agent_get - summary: Get agent - description: >- - Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the - agent ID. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for agent_get - required: true - content: - application/json: - example: - tool: agent_get - arguments: - agentId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - agent_get - arguments: - $ref: '#/components/schemas/GetAgentInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentGet' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /agent-list: - post: - operationId: agent_list - summary: List agents - description: >- - List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, - organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - tags: - - Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for agent_list - required: true - content: - application/json: - example: - tool: agent_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - agent_list - arguments: - $ref: '#/components/schemas/ListAgentsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/AgentList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-get: - post: - operationId: tactic_get - summary: Get tactic - description: Get detailed information about a specific tactic. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for tactic_get - required: true - content: - application/json: - example: - tool: tactic_get - arguments: - tacticId: 100 - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_get - arguments: - $ref: '#/components/schemas/GetTacticInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticGetOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /tactic-list: - post: - operationId: tactic_list - summary: List tactics - description: List all tactics with optional filtering by brand agent or campaign. - tags: - - Tactics - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for tactic_list - required: true - content: - application/json: - example: - tool: tactic_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - tactic_list - arguments: - $ref: '#/components/schemas/ListTacticsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/TacticList' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /outcomes-agent-get-proposals: - post: - operationId: outcomes_agent_get_proposals - summary: Get proposals from outcome agents - description: >- - Request tactical proposals from outcome agents for a campaign. Outcome agents analyze the campaign brief and - budget to propose execution strategies. - tags: - - Outcome Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for outcomes_agent_get_proposals - required: true - content: - application/json: - example: - tool: outcomes_agent_get_proposals - arguments: - campaignId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - outcomes_agent_get_proposals - arguments: - $ref: '#/components/schemas/OutcomesAgentGetProposalsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/OutcomesAgentGetProposals' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /outcomes-agent-accept-proposal: - post: - operationId: outcomes_agent_accept_proposal - summary: Accept outcome agent proposal - description: Accept a proposal from an outcome agent, creating a tactic and assigning it to the agent for management. - tags: - - Outcome Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for outcomes_agent_accept_proposal - required: true - content: - application/json: - example: - tool: outcomes_agent_accept_proposal - arguments: - proposalId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - outcomes_agent_accept_proposal - arguments: - $ref: '#/components/schemas/OutcomesAgentAcceptProposalInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/OutcomesAgentAcceptProposal' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /outcomes-agent-list-tactics: - post: - operationId: outcomes_agent_list_tactics - summary: List tactics by outcome agent - description: List all tactics managed by a specific outcome agent. - tags: - - Outcome Agents - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for outcomes_agent_list_tactics - required: true - content: - application/json: - example: - tool: outcomes_agent_list_tactics - arguments: - outcomeAgentId: example_id_123 - schema: - type: object - properties: - tool: - type: string - enum: - - outcomes_agent_list_tactics - arguments: - $ref: '#/components/schemas/OutcomesAgentListTacticsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/OutcomesAgentListTactics' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-create: - post: - operationId: service_token_create - summary: Create service token - description: >- - Create a new service token for API authentication. Returns the full token which should be stored securely as it - cannot be retrieved later. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_create - required: true - content: - application/json: - example: - tool: service_token_create - arguments: - name: Example Name - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_create - arguments: - $ref: '#/components/schemas/CreateServiceTokenInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/CreateServiceTokenOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-list: - post: - operationId: service_token_list - summary: List service tokens - description: List all service tokens for the authenticated customer. Secrets are never returned, only metadata. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_list - required: true - content: - application/json: - example: - tool: service_token_list - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_list - arguments: - $ref: '#/components/schemas/ListServiceTokensInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/ListServiceTokensOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-get: - post: - operationId: service_token_get - summary: Get service token - description: Get detailed information about a specific service token. The secret is never returned. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_get - required: true - content: - application/json: - example: - tool: service_token_get - arguments: - id: '1234567890' - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_get - arguments: - $ref: '#/components/schemas/GetServiceTokenInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/GetServiceTokenOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-update: - post: - operationId: service_token_update - summary: Update service token - description: Update a service token. Only name, description, and expiration can be modified. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_update - required: true - content: - application/json: - example: - tool: service_token_update - arguments: - id: '1234567890' - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_update - arguments: - $ref: '#/components/schemas/UpdateServiceTokenInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/UpdateServiceTokenOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /service-token-archive: - post: - operationId: service_token_archive - summary: Archive service token - description: Archive (soft delete) a service token. This immediately invalidates the token for authentication. - tags: - - Service Tokens - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for service_token_archive - required: true - content: - application/json: - example: - tool: service_token_archive - arguments: - id: '1234567890' - schema: - type: object - properties: - tool: - type: string - enum: - - service_token_archive - arguments: - $ref: '#/components/schemas/ArchiveServiceTokenInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/ArchiveServiceTokenOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /customer-get: - post: - operationId: customer_get - summary: Get customer info - description: Get detailed information about a customer from the core database. - tags: - - Customers - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for customer_get - required: true - content: - application/json: - example: - tool: customer_get - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - customer_get - arguments: - $ref: '#/components/schemas/GetCustomerInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/GetCustomerOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' - /customer-get-seats: - post: - operationId: customer_get_seats - summary: Get customer seats - description: Get all seats associated with a customer from the core database. - tags: - - Customers - security: - - bearerAuth: [] - parameters: - - name: mcp-session-id - in: header - required: true - schema: - type: string - format: uuid - description: >- - MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a - session ID, then reuse it for all subsequent tool requests in the same session. - requestBody: - description: Request body for customer_get_seats - required: true - content: - application/json: - example: - tool: customer_get_seats - arguments: {} - schema: - type: object - properties: - tool: - type: string - enum: - - customer_get_seats - arguments: - $ref: '#/components/schemas/GetCustomerSeatsInput' - required: - - tool - - arguments - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/MCPContent' - structuredContent: - $ref: '#/components/schemas/GetCustomerSeatsOutput' - required: - - content - - structuredContent - additionalProperties: false - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/BadRequest' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Unauthorized' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/InternalError' -components: - schemas: - BudgetRange: - description: Budget range for campaign planning - type: object - properties: - min: - description: Minimum budget available - example: 50000 - type: number - minimum: 0 - exclusiveMinimum: true - max: - description: Maximum budget available - example: 150000 - type: number - minimum: 0 - exclusiveMinimum: true - currency: - description: Currency for budget (ISO 4217 code) - example: USD - default: USD - type: string - minLength: 3 - maxLength: 3 - required: - - min - - max - ProposalCard: - description: Visual card data for rendering proposals in marketplace UI, following ADCP product card pattern - type: object - properties: - title: - description: Proposal name/title - example: Premium Display Campaign - type: string - description: - description: What the proposal offers - example: Target premium inventory at $2.50 vCPM with 85% viewability guarantee - type: string - image_carousel: - description: Optional array of image URLs showcasing the approach - example: - - https://example.com/chart1.png - - https://example.com/viz2.png - type: array - items: - type: string - format: uri - details: - description: Markdown-formatted detailed execution plan and specifications - example: |- - ## Execution Strategy - - We will target... - type: string - pricing_summary: - description: Pricing information for comparison - type: object - properties: - method: - description: Human-readable pricing method - example: 15% revenue share - type: string - budget_capacity: - description: Human-readable budget capacity - example: $50,000 maximum - type: string - estimated_cost: - description: Optional estimated cost calculation - example: $7,500 estimated fee - type: string - required: - - method - - budget_capacity - required: - - title - - description - - pricing_summary - ListAssetsInput: - type: object - properties: - brandAgentId: - description: Optional brand agent ID to filter assets - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - ListBrandAgentsInput: - description: Parameters for listing brand agents. Authentication is automatic. - type: object - properties: - where: - description: Prisma-style where clause for filtering agents - type: object - additionalProperties: {} - orderBy: - description: Prisma-style orderBy clause - type: object - additionalProperties: {} - take: - description: Number of records to return - example: 10 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - skip: - description: Number of records to skip - example: 0 - type: integer - minimum: 0 - maximum: 9007199254740991 - distinct: - description: Fields to use for distinct selection - type: array - items: - type: string - example: [] - GetBrandAgentInput: - description: Parameters for retrieving a specific brand agent - type: object - properties: - brandAgentId: - description: The unique identifier for the brand agent - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - required: - - brandAgentId - CreateBrandAgentInput: - description: Parameters for creating a new brand agent - type: object - properties: - name: - description: Name of the brand agent (advertiser account) - example: Nike Global Campaigns - type: string - minLength: 1 - maxLength: 255 - description: - description: Optional description of the brand agent - example: Brand agent for Nike global advertising campaigns - type: string - maxLength: 1000 - manifestUrl: - description: URL to the brand manifest - example: https://example.com/brand-manifest - type: string - format: uri - countryCodes: - description: Country codes (ISO 3166-1 alpha-2) - example: - - US - - CA - - GB - type: array - items: - type: string - minLength: 2 - maxLength: 2 - required: - - name - UpdateBrandAgentInput: - description: Parameters for updating a brand agent - type: object - properties: - brandAgentId: - description: The unique identifier for the brand agent - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - name: - description: Updated name of the brand agent - type: string - minLength: 1 - maxLength: 255 - example: Example Name - description: - description: Updated description - type: string - maxLength: 1000 - example: string - manifestUrl: - description: Updated URL to the brand manifest - example: https://example.com/brand-manifest - type: string - format: uri - countryCodes: - description: Updated country codes - type: array - items: - type: string - minLength: 2 - maxLength: 2 - example: [] - required: - - brandAgentId - DeleteBrandAgentInput: - description: Parameters for deleting a brand agent - type: object - properties: - brandAgentId: - description: The unique identifier for the brand agent to delete - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - required: - - brandAgentId - CreateBrandStandardInput: - type: object - properties: - brandAgentId: - description: Brand agent ID - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - name: - description: Standard name - type: string - minLength: 1 - maxLength: 255 - example: Example Name - description: - description: Standard description - type: string - example: string - prompt: - description: Brand standards prompt - type: string - minLength: 1 - example: string - isPrimary: - description: Whether this is the primary standard - type: boolean - example: true - countries: - description: Country codes - type: array - items: - type: string - example: [] - channels: - description: Channel types - type: array - items: - type: string - enum: - - ctv - - video - - display - - app - - social - example: [] - brands: - description: Brand names - type: array - items: - type: string - example: [] - required: - - brandAgentId - - prompt - DeleteBrandStandardInput: - type: object - properties: - brandStandardId: - description: Brand standard ID - type: string - example: example_id_123 - required: - - brandStandardId - ListBrandStandardsInput: - type: object - properties: - brandAgentId: - description: Optional brand agent ID to filter brand standards by - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - where: - description: Prisma-style where clause for filtering standards - type: object - additionalProperties: {} - orderBy: - description: Prisma-style orderBy clause - type: object - additionalProperties: {} - take: - description: Number of records to return - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - description: Number of records to skip - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - distinct: - description: Fields to use for distinct selection - type: array - items: - type: string - example: [] - CreateBrandStoryInput: - type: object - properties: - brandAgentId: - description: Brand agent ID (bigint or string) - anyOf: - - type: integer - format: int64 - - type: string - name: - description: Story name - type: string - minLength: 1 - maxLength: 255 - example: Example Name - prompt: - description: Brand story prompt - type: string - example: string - brands: - description: Brand names - type: array - items: - type: string - example: [] - languages: - description: Language codes (use language_list tool to see available options) - type: array - items: - type: string - example: [] - required: - - brandAgentId - - name - - languages - UpdateBrandStoryInput: - type: object - properties: - brandStoryId: - description: Brand story ID - type: string - example: example_id_123 - name: - description: Story name - type: string - example: Example Name - prompt: - description: Updated brand story prompt - type: string - minLength: 1 - example: string - required: - - brandStoryId - - prompt - DeleteBrandStoryInput: - type: object - properties: - brandStoryId: - description: Brand story ID - type: string - example: example_id_123 - required: - - brandStoryId - ListBrandStoriesInput: - type: object - properties: - brandAgentId: - description: Optional brand agent ID to filter brand stories by - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - where: - description: Filtering criteria - type: object - additionalProperties: {} - orderBy: - description: Ordering criteria - type: object - additionalProperties: {} - take: - description: Number of records to return - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - description: Number of records to skip - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - distinct: - description: Fields to use for distinct selection - type: array - items: - type: string - example: [] - ListCampaignsInput: - description: Parameters for listing campaigns - type: object - properties: - brandAgentId: - description: Filter by brand agent ID - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - status: - description: Filter by campaign status - type: string - enum: - - ACTIVE - - PAUSED - - ARCHIVED - - DRAFT - example: ACTIVE - limit: - description: Number of results to return - example: 50 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - offset: - description: Number of results to skip for pagination - example: 0 - type: integer - minimum: 0 - maximum: 9007199254740991 - CreateCampaignInput: - description: Parameters for creating a new campaign - type: object - properties: - brandAgentId: - description: Brand agent ID that will own this campaign - example: 123 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - name: - description: Optional name for the campaign (auto-generated if not provided) - example: Summer 2025 Tech Campaign - type: string - minLength: 1 - maxLength: 255 - prompt: - description: >- - Natural language description of campaign requirements. The backend will parse this to extract targeting, - budget, and creative requirements. - example: Create a video campaign targeting tech enthusiasts aged 25-45 with $50k budget - type: string - minLength: 10 - budget: - description: Budget configuration for the campaign - type: object - properties: - total: - type: number - minimum: 0 - exclusiveMinimum: true - currency: - default: USD - type: string - minLength: 3 - maxLength: 3 - dailyCap: - type: number - minimum: 0 - exclusiveMinimum: true - pacing: - type: string - enum: - - EVEN - - ASAP - - FRONTLOADED - required: - - total - startDate: - description: Campaign start date (ISO 8601 format) - example: '2025-01-15T00:00:00Z' - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - endDate: - description: Campaign end date (ISO 8601 format) - example: '2025-03-31T23:59:59Z' - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - scoringWeights: - description: Scoring weights for campaign optimization - type: object - properties: - affinity: - type: number - minimum: 0 - maximum: 1 - outcome: - type: number - minimum: 0 - maximum: 1 - quality: - type: number - minimum: 0 - maximum: 1 - outcomeScoreWindowDays: - description: Number of days for outcome measurement window - example: 30 - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - status: - description: Initial campaign status - type: string - enum: - - ACTIVE - - PAUSED - - ARCHIVED - - DRAFT - example: ACTIVE - required: - - brandAgentId - - prompt - GetCampaignInput: - description: Parameters for retrieving a specific campaign - type: object - properties: - campaignId: - description: The unique identifier for the campaign - example: cmp_987654321 - type: string - minLength: 1 - required: - - campaignId - UpdateCampaignInput: - description: Parameters for updating a campaign - type: object - properties: - campaignId: - description: The unique identifier for the campaign - example: cmp_987654321 - type: string - minLength: 1 - name: - description: Updated campaign name - type: string - minLength: 1 - maxLength: 255 - example: Example Name - prompt: - description: Updated campaign prompt - type: string - minLength: 10 - example: string - budget: - description: Updated budget configuration - type: object - properties: - total: - type: number - minimum: 0 - exclusiveMinimum: true - currency: - default: USD - type: string - minLength: 3 - maxLength: 3 - dailyCap: - type: number - minimum: 0 - exclusiveMinimum: true - pacing: - type: string - enum: - - EVEN - - ASAP - - FRONTLOADED - startDate: - description: Updated start date - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - endDate: - description: Updated end date - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - scoringWeights: - description: Updated scoring weights - type: object - properties: - affinity: - type: number - minimum: 0 - maximum: 1 - outcome: - type: number - minimum: 0 - maximum: 1 - quality: - type: number - minimum: 0 - maximum: 1 - outcomeScoreWindowDays: - description: Updated outcome score window days - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - status: - description: Updated campaign status - type: string - enum: - - ACTIVE - - PAUSED - - ARCHIVED - - DRAFT - example: ACTIVE - required: - - campaignId - DeleteCampaignInput: - description: Parameters for deleting a campaign - type: object - properties: - campaignId: - description: The unique identifier for the campaign to delete - example: cmp_987654321 - type: string - minLength: 1 - hardDelete: - description: 'If true, permanently delete the campaign. Default: false (soft delete/archive)' - type: boolean - example: true - required: - - campaignId - GetCampaignSummaryInput: - type: object - properties: - campaignId: - description: Campaign ID - type: string - example: example_id_123 - required: - - campaignId - ListCampaignTacticsInput: - type: object - properties: - campaignId: - description: Campaign ID - type: string - example: example_id_123 - required: - - campaignId - ValidateBriefInput: - type: object - properties: - brief: - description: Campaign brief text - type: string - minLength: 10 - example: string - required: - - brief - ListChannelsInput: - type: object - properties: {} - GetCustomerInput: - type: object - properties: - customerId: - description: >- - The unique identifier of the customer to retrieve. If not provided, uses the authenticated users customer - ID. - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - GetCustomerSeatsInput: - type: object - properties: - customerId: - description: >- - The unique identifier of the customer whose seats to retrieve. If not provided, uses the authenticated users - customer ID. - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - AssignCreativeInput: - type: object - properties: - creativeId: - type: string - example: example_id_123 - campaignId: - type: string - example: example_id_123 - required: - - creativeId - - campaignId - CreateCreativeInput: - type: object - properties: - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - organizationId: - type: string - example: example_id_123 - name: - type: string - minLength: 1 - maxLength: 255 - example: Example Name - description: - type: string - example: string - formatSource: - type: string - enum: - - ADCP - - CREATIVE_AGENT - - PUBLISHER - example: ADCP - formatId: - description: >- - Format identifier. For ADCP sources, this should be a format ID string recognized by the target sales agent - (e.g., display_300x250, video_1920x1080). Valid formats are agent-specific. - type: string - example: example_id_123 - mediaUrl: - type: string - example: https://example.com - assets: - description: >- - Optional: Upload assets inline with the creative. Each asset requires: name, contentType, data (base64), and - assetType. - type: array - items: - type: object - properties: - name: - description: Filename (e.g., banner.png) - type: string - contentType: - description: MIME type (e.g., image/png, image/jpeg) - type: string - data: - description: Base64-encoded file data (without data:image/png;base64, prefix) - format: byte - type: string - assetType: - description: Type of asset - type: string - enum: - - image - - video - - audio - - logo - - font - tags: - description: Optional tags - type: array - items: - type: string - required: - - name - - contentType - - data - - assetType - example: [] - content: - type: object - additionalProperties: {} - assemblyMethod: - type: string - enum: - - CREATIVE_AGENT - - ACTIVATION - - PUBLISHER - example: CREATIVE_AGENT - campaignId: - description: Optional campaign ID (object ID) to assign creative to - type: string - example: example_id_123 - required: - - brandAgentId - - name - UpdateCreativeInput: - type: object - properties: - creativeId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - status: - type: string - example: string - required: - - creativeId - DeleteCreativeInput: - type: object - properties: - creativeId: - type: string - example: example_id_123 - required: - - creativeId - GetCreativeInput: - type: object - properties: - creativeId: - type: string - example: example_id_123 - required: - - creativeId - ListCreativesInput: - type: object - properties: - campaignId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - brandAgentId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - formatSource: - type: string - enum: - - ADCP - - CREATIVE_AGENT - - PUBLISHER - example: ADCP - status: - type: string - enum: - - ACTIVE - - PAUSED - - ARCHIVED - - DRAFT - example: ACTIVE - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - ListCountriesInput: - type: object - properties: {} - ListLanguagesInput: - type: object - properties: {} - GetMediaBuyInput: - type: object - properties: - mediaBuyId: - type: string - example: example_id_123 - required: - - mediaBuyId - ListMediaBuysInput: - type: object - properties: - tacticId: - type: number - example: 100 - status: - type: string - enum: - - DRAFT - - PENDING_APPROVAL - - ACTIVE - - PAUSED - - COMPLETED - - FAILED - - REJECTED - example: DRAFT - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - OutcomesAgentGetProposalsInput: - type: object - properties: - campaignId: - description: Campaign ID to get proposals for - example: camp_123 - type: string - agentIds: - description: 'Optional: Specific outcome agent IDs to query. If omitted, queries all outcome agents.' - example: - - agent_123 - - agent_456 - type: array - items: - type: string - budgetRange: - allOf: - - $ref: '#/components/schemas/BudgetRange' - startDate: - description: Campaign start date (ISO 8601) - example: '2025-01-01T00:00:00Z' - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - endDate: - description: Campaign end date (ISO 8601) - example: '2025-01-31T23:59:59Z' - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - channels: - description: Advertising channels - example: - - display - - video - type: array - items: - type: string - enum: - - ctv - - video - - display - - app - - social - countries: - description: ISO 3166-1 alpha-2 country codes - example: - - US - - CA - type: array - items: - type: string - brief: - description: Campaign brief text - type: string - example: string - required: - - campaignId - OutcomesAgentAcceptProposalInput: - type: object - properties: - proposalId: - description: Database ID of the proposal to accept - example: '123' - type: string - tacticName: - description: >- - Optional: Name for the tactic/strategy that will be created. If not provided, a unique identifier will be - generated. - example: Premium Display Campaign - type: string - customFields: - description: Optional custom fields required by the outcome agent - type: object - additionalProperties: {} - required: - - proposalId - OutcomesAgentListTacticsInput: - type: object - properties: - outcomeAgentId: - description: ID of the outcome agent to list tactics for - example: '123' - type: string - required: - - outcomeAgentId - ListProductsInput: - type: object - properties: - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - GetAgentInput: - type: object - properties: - agentId: - description: The agent ID to retrieve - type: string - example: example_id_123 - required: - - agentId - ListAgentsInput: - type: object - properties: - type: - description: Filter by agent type (SALES or OUTCOME) - type: string - enum: - - SALES - - OUTCOME - example: SALES - status: - description: Filter by status (PENDING, ACTIVE, DISABLED) - type: string - enum: - - PENDING - - ACTIVE - - DISABLED - example: PENDING - organizationId: - description: Filter by organization ID - type: string - example: example_id_123 - relationship: - description: >- - Filter by relationship (SELF = owned by you, SCOPE3 = Scope3-provided, MARKETPLACE = third-party marketplace - agents) - type: string - enum: - - SELF - - SCOPE3 - - MARKETPLACE - example: SELF - name: - description: Filter by agent name (partial match) - type: string - example: Example Name - GetTacticInput: - type: object - properties: - tacticId: - type: number - example: 100 - required: - - tacticId - ListTacticsInput: - type: object - properties: - campaignId: - type: string - example: example_id_123 - take: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - skip: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - CreateServiceTokenInput: - type: object - properties: - name: - description: Human-readable name for the service token - type: string - minLength: 1 - example: Example Name - description: - description: Optional description of the token purpose and usage - type: string - example: string - expiresInDays: - description: Number of days until token expiration (max 365). If not provided, token does not expire - type: integer - exclusiveMinimum: true - maximum: 365 - example: 100 - scope: - description: 'Token scope: CUSTOMER (full customer access) or SEAT (scoped to specific seat)' - default: CUSTOMER - type: string - enum: - - CUSTOMER - - SEAT - seatName: - description: Seat name (required when scope is SEAT). The seat will be looked up for the customer. - type: string - minLength: 1 - example: Example Name - required: - - name - UpdateServiceTokenInput: - type: object - properties: - id: - description: The unique identifier of the service token to update - type: integer - format: int64 - example: 100 - name: - description: Updated human-readable name for the service token - type: string - minLength: 1 - example: Example Name - description: - description: Updated description of the token purpose and usage - type: string - example: string - expiresInDays: - description: Number of days to extend expiration from now (max 365). Updates the expiresAt timestamp - type: integer - exclusiveMinimum: true - maximum: 365 - example: 100 - required: - - id - ArchiveServiceTokenInput: - type: object - properties: - id: - description: The unique identifier of the service token to archive - type: integer - format: int64 - example: 100 - required: - - id - GetServiceTokenInput: - type: object - properties: - id: - description: The unique identifier of the service token to retrieve - type: integer - format: int64 - example: 100 - includeSecret: - description: Whether to fetch the access_client_secret from Google Secret Manager. Defaults to false for security - default: false - type: boolean - required: - - id - ListServiceTokensInput: - type: object - properties: - includeArchived: - description: Whether to include archived tokens in the response - default: false - type: boolean - seatId: - description: Filter tokens by seat ID - type: integer - format: int64 - example: 100 - userId: - description: Filter tokens by user ID - type: integer - format: int64 - example: 100 - BrandAgentUpdate: - type: object - properties: - id: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - manifestUrl: - type: string - format: uri - example: https://example.com - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - customerId - - createdAt - - updatedAt - BrandStandardsCreate: - type: object - properties: - id: - type: string - example: example_id_123 - name: - type: string - example: Example Name - description: - type: string - example: string - countryCodes: - type: array - items: - type: string - example: [] - channelCodes: - type: array - items: - type: string - example: [] - brands: - type: array - items: - type: string - example: [] - models: - type: array - items: - type: object - properties: - id: - type: string - name: - type: string - prompt: - type: string - status: - nullable: true - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - prompt - - status - - createdAt - - updatedAt - example: [] - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - countryCodes - - channelCodes - - brands - - models - - createdAt - - updatedAt - CampaignUpdate: - type: object - properties: - campaignId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - status: - type: string - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - campaignId - - name - - status - - createdAt - - updatedAt - CreativeGet: - type: object - properties: - creativeId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - status: - type: string - example: string - campaignId: - type: string - example: example_id_123 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - creativeId - - name - - status - - createdAt - - updatedAt - MediaBuyGet: - type: object - properties: - id: - type: string - example: example_id_123 - tacticId: - type: number - example: 100 - customerId: - type: number - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - required: - - mediaProductId - - salesAgentId - example: [] - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - example: [] - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - example: [] - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - status: - type: string - example: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - TacticGet: - type: object - properties: - id: - type: number - example: 100 - name: - type: string - example: Example Name - prompt: - type: string - example: string - campaignIds: - type: array - items: - type: string - example: [] - channelCodes: - type: array - items: - type: string - example: [] - countryCodes: - type: array - items: - type: string - example: [] - mediaBuyCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - channelCodes - - countryCodes - - createdAt - - updatedAt - MCPContent: - type: object - properties: - type: - type: string - enum: - - text - example: text - text: - type: string - example: string - required: - - type - - text - additionalProperties: false - BadRequest: - description: Bad request error response - type: object - properties: - error: - type: string - example: string - message: - type: string - example: string - required: - - error - additionalProperties: false - Unauthorized: - description: Unauthorized error response - type: object - properties: - error: - type: string - example: string - message: - type: string - example: string - required: - - error - additionalProperties: false - InternalError: - description: Internal server error response - type: object - properties: - error: - type: string - example: string - message: - type: string - example: string - required: - - error - additionalProperties: false - AssetList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - assetId: - type: string - originalFilename: - type: string - assetType: - type: string - size: - type: number - brandAgentId: - type: string - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - signedUrl: - type: string - tags: - type: array - items: - type: string - required: - - assetId - - originalFilename - - assetType - - size - - brandAgentId - - customerId - - signedUrl - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - BrandAgentList: - type: object - properties: - brandAgents: - type: array - items: - $ref: '#/components/schemas/BrandAgentUpdateOutput' - example: [] - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - brandAgents - - total - additionalProperties: false - BrandAgentDelete: - type: object - properties: - success: - type: boolean - example: true - deletedId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - required: - - success - - deletedId - additionalProperties: false - BrandStandardsDelete: - type: object - properties: - success: - type: boolean - example: true - id: - type: string - example: example_id_123 - required: - - success - - id - additionalProperties: false - BrandStandardsList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - $ref: '#/components/schemas/BrandStandardsCreateOutput' - example: [] - required: - - total - - items - additionalProperties: false - BrandStoryCreate: - type: object - properties: - id: - type: string - example: example_id_123 - name: - type: string - example: Example Name - brandAgentId: - type: string - example: example_id_123 - countryCodes: - type: array - items: - type: string - example: [] - channelCodes: - type: array - items: - type: string - example: [] - languages: - type: array - items: - type: string - example: [] - brands: - type: array - items: - type: string - example: [] - currentModel: - type: object - properties: - id: - type: string - name: - type: string - prompt: - type: string - status: - nullable: true - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - prompt - - status - - createdAt - - updatedAt - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - createdAt - - updatedAt - additionalProperties: false - BrandStoryUpdate: - type: object - properties: - id: - type: string - example: example_id_123 - name: - type: string - example: Example Name - prompt: - type: string - example: string - status: - type: string - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - createdAt - - updatedAt - additionalProperties: false - BrandStoryDelete: - type: object - properties: - success: - type: boolean - example: true - id: - type: string - example: example_id_123 - required: - - success - - id - additionalProperties: false - BrandStoryList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - id: - type: string - name: - type: string - description: - type: string - status: - type: string - type: - type: string - languages: - type: array - items: - type: string - currentModel: - type: object - properties: - id: - type: string - name: - type: string - prompt: - type: string - status: - nullable: true - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - prompt - - status - - createdAt - - updatedAt - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - status - - type - - languages - - createdAt - - updatedAt - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - CampaignList: - type: object - properties: - campaigns: - type: array - items: - $ref: '#/components/schemas/CampaignUpdateOutput' - example: [] - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - campaigns - - total - additionalProperties: false - CampaignDelete: - type: object - properties: - success: - type: boolean - example: true - deletedId: - type: string - example: example_id_123 - required: - - success - - deletedId - additionalProperties: false - CampaignGetSummary: - type: object - properties: - campaignId: - type: string - example: example_id_123 - summary: - type: object - additionalProperties: {} - required: - - campaignId - - summary - additionalProperties: false - CampaignListTactics: - type: object - properties: - tactics: - type: array - items: {} - example: [] - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - tactics - - total - additionalProperties: false - CampaignValidateBrief: - type: object - properties: - valid: - type: boolean - example: true - feedback: - type: string - example: string - required: - - valid - additionalProperties: false - ChannelList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - channel: - type: string - displayName: - type: string - required: - - channel - - displayName - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - GetCustomerOutput: - type: object - properties: - id: - description: Unique identifier for the customer - type: number - example: 100 - company: - description: Company name - type: string - example: string - name: - description: Customer display name - type: string - example: Example Name - active: - description: Whether the customer is currently active - type: boolean - example: true - createdAt: - description: ISO 8601 timestamp when the customer was created - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - company - - name - - active - - createdAt - additionalProperties: false - GetCustomerSeatsOutput: - type: object - properties: - customerId: - description: The customer ID these seats belong to - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - seats: - description: Array of seats belonging to the customer - type: array - items: - type: object - properties: - id: - description: Unique identifier for the seat - type: string - name: - description: Seat display name - type: string - customerId: - description: Customer ID that owns this seat - type: number - active: - description: Whether the seat is currently active - type: boolean - required: - - id - - name - - customerId - - active - additionalProperties: false - example: [] - count: - description: Total number of seats returned - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - customerId - - seats - - count - additionalProperties: false - CreativeAssign: - type: object - properties: - success: - type: boolean - example: true - creativeId: - type: string - example: example_id_123 - campaignId: - type: string - example: example_id_123 - required: - - success - - creativeId - - campaignId - additionalProperties: false - CreativeDelete: - type: object - properties: - success: - type: boolean - example: true - id: - type: string - example: example_id_123 - required: - - success - - id - additionalProperties: false - CreativeList: - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/CreativeGetOutput' - example: [] - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - items - - total - additionalProperties: false - CountryList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - key: - type: string - displayName: - type: string - required: - - key - - displayName - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - LanguageList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - key: - type: string - displayName: - type: string - required: - - key - - displayName - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - MediaBuyList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - $ref: '#/components/schemas/MediaBuyGetOutput' - example: [] - required: - - total - - items - additionalProperties: false - OutcomesAgentGetProposals: - type: object - properties: - total: - description: Total number of proposals returned - type: number - example: 100 - proposals: - description: List of proposals from outcome agents - type: array - items: - type: object - properties: - id: - description: Database ID of the proposal - type: string - proposalId: - description: Outcome agent generated proposal ID - type: string - outcomeAgentId: - description: ID of the outcome agent that created this proposal - type: string - outcomeAgentName: - description: Name of the outcome agent - type: string - execution: - description: How the proposal would be executed - type: string - budgetCapacity: - description: Maximum budget the agent can manage - type: number - pricing: - description: Pricing model for the proposal - type: object - properties: - method: - type: string - enum: - - revshare - - cost_per_unit - rate: - type: number - pricing_model: - type: string - enum: - - cpm - - cpc - - cpa - - cpv - - cpcv - currency: - type: string - required: - - method - - rate - - currency - additionalProperties: false - sku: - description: Tactic type identifier - type: string - status: - description: Current status of the proposal - type: string - enum: - - pending - - accepted - - rejected - - expired - proposalCard: - description: Visual card data for rendering in UI - allOf: - - $ref: '#/components/schemas/ProposalCardOutput' - createdAt: - description: When the proposal was created - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - proposalId - - outcomeAgentId - - outcomeAgentName - - execution - - budgetCapacity - - pricing - - status - - createdAt - additionalProperties: false - example: [] - required: - - total - - proposals - additionalProperties: false - OutcomesAgentAcceptProposal: - type: object - properties: - tacticId: - description: ID of the created tactic/strategy - type: string - example: example_id_123 - tacticName: - description: Name of the created tactic (user-provided or auto-generated) - type: string - example: Example Name - proposalId: - description: ID of the accepted proposal - type: string - example: example_id_123 - outcomeAgentId: - description: ID of the outcome agent managing this tactic - type: string - example: example_id_123 - acknowledged: - description: Whether the outcome agent acknowledged the assignment - type: boolean - example: true - message: - description: Optional message from the outcome agent - type: string - example: string - required: - - tacticId - - tacticName - - proposalId - - outcomeAgentId - - acknowledged - additionalProperties: false - OutcomesAgentListTactics: - type: object - properties: - outcomeAgentId: - description: ID of the outcome agent - type: string - example: example_id_123 - outcomeAgentName: - description: Name of the outcome agent - type: string - example: Example Name - total: - description: Total number of tactics managed by this agent - type: number - example: 100 - tactics: - description: List of tactics managed by this outcome agent - type: array - items: - type: object - properties: - tacticId: - description: ID of the tactic (strategy) - type: string - tacticName: - description: Name of the tactic - type: string - proposalId: - description: ID of the original proposal - type: string - acceptedAt: - description: When the proposal was accepted (ISO 8601) - type: string - campaignId: - description: Campaign ID if linked to a campaign - nullable: true - type: string - required: - - tacticId - - tacticName - - proposalId - - acceptedAt - - campaignId - additionalProperties: false - example: [] - required: - - outcomeAgentId - - outcomeAgentName - - total - - tactics - additionalProperties: false - MediaProductList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - type: object - properties: - id: - type: string - productId: - type: string - name: - type: string - salesAgent: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - deliveryType: - type: string - enum: - - guaranteed - - non_guaranteed - format: - type: string - creativeFormats: - anyOf: - - type: array - items: - type: string - - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - id - - productId - - name - - deliveryType - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - AgentGet: - anyOf: - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - authenticationType: - type: string - description: - type: string - organizationId: - type: string - registeredBy: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - - authenticationType - - createdAt - - updatedAt - additionalProperties: false - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - authenticationType: - type: string - description: - type: string - organizationId: - type: string - registeredBy: - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - customerAccountCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - - authenticationType - - createdAt - - updatedAt - - customerAccountCount - additionalProperties: false - AgentList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - anyOf: - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - additionalProperties: false - - type: object - properties: - agentId: - type: string - name: - type: string - type: - type: string - enum: - - SALES - - OUTCOME - status: - type: string - relationship: - type: string - endpointUrl: - type: string - protocol: - type: string - customerAccountCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - required: - - agentId - - name - - type - - status - - relationship - - endpointUrl - - protocol - - customerAccountCount - additionalProperties: false - example: [] - required: - - total - - items - additionalProperties: false - TacticList: - type: object - properties: - total: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - items: - type: array - items: - $ref: '#/components/schemas/TacticGetOutput' - example: [] - required: - - total - - items - additionalProperties: false - CreateServiceTokenOutput: - type: object - properties: - id: - description: Unique identifier for the service token - type: integer - format: int64 - example: 100 - customerId: - description: Customer ID that owns this token - type: number - example: 100 - seatId: - description: Seat ID if token is scoped to a specific seat - type: integer - format: int64 - example: 100 - userId: - description: User ID if token is scoped to a specific user - type: integer - format: int64 - example: 100 - organizationId: - description: Optional organization identifier for scoping the token - type: string - example: example_id_123 - name: - description: Human-readable name of the token - type: string - example: Example Name - description: - description: Description of the token purpose - type: string - example: string - accessClientId: - description: The public client ID portion of the token credentials (safe to log) - type: string - example: example_id_123 - accessClientSecret: - description: The secret portion of the token credentials. ONLY returned on creation, never retrievable again! - type: string - example: string - expiresAt: - description: ISO 8601 timestamp when the token expires, if set - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - description: ISO 8601 timestamp when the token was created - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - customerId - - name - - accessClientId - - accessClientSecret - - createdAt - additionalProperties: false - UpdateServiceTokenOutput: - type: object - properties: - id: - description: Unique identifier for the service token - type: integer - format: int64 - example: 100 - name: - description: Updated human-readable name of the token - type: string - example: Example Name - description: - description: Updated description of the token purpose - type: string - example: string - expiresAt: - description: ISO 8601 timestamp when the token expires, if updated - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - description: ISO 8601 timestamp when the token was last updated - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - updatedAt - additionalProperties: false - ArchiveServiceTokenOutput: - type: object - properties: - id: - description: Unique identifier for the archived token - type: integer - format: int64 - example: 100 - archivedAt: - description: ISO 8601 timestamp when the token was archived - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - archivedAt - additionalProperties: false - GetServiceTokenOutput: - type: object - properties: - id: - description: Unique identifier for the service token - type: integer - format: int64 - example: 100 - customerId: - description: Customer ID that owns this token - type: number - example: 100 - seatId: - description: Seat ID if token is scoped to a specific seat - type: integer - format: int64 - example: 100 - userId: - description: User ID if token is scoped to a specific user - type: integer - format: int64 - example: 100 - organizationId: - description: Optional organization identifier for scoping the token - type: string - example: example_id_123 - name: - description: Human-readable name of the token - type: string - example: Example Name - description: - description: Description of the token purpose - type: string - example: string - accessClientId: - description: The public client ID portion of the token credentials (safe to log) - type: string - example: example_id_123 - accessClientSecret: - description: The secret portion of the token credentials. Only included if includeSecret=true was passed - type: string - example: string - expiresAt: - description: ISO 8601 timestamp when the token expires, if set - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - description: ISO 8601 timestamp when the token was created - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - description: ISO 8601 timestamp when the token was last updated - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - archivedAt: - description: ISO 8601 timestamp when the token was archived, if archived - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - customerId - - name - - accessClientId - - createdAt - - updatedAt - additionalProperties: false - ListServiceTokensOutput: - type: object - properties: - tokens: - description: 'Array of service tokens. Note: accessClientSecret is never included in list responses' - type: array - items: - type: object - properties: - id: - description: Unique identifier for the service token - type: integer - format: int64 - customerId: - description: Customer ID that owns this token - type: number - seatId: - description: Seat ID if token is scoped to a specific seat - type: integer - format: int64 - seatName: - description: Seat name if token is scoped to a specific seat - type: string - userId: - description: User ID if token is scoped to a specific user - type: integer - format: int64 - organizationId: - description: Optional organization identifier for scoping the token - type: string - name: - description: Human-readable name of the token - type: string - description: - description: Description of the token purpose - type: string - accessClientId: - description: The public client ID portion of the token credentials (safe to log) - type: string - expiresAt: - description: ISO 8601 timestamp when the token expires, if set - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - createdAt: - description: ISO 8601 timestamp when the token was created - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - description: ISO 8601 timestamp when the token was last updated - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - archivedAt: - description: ISO 8601 timestamp when the token was archived, if archived - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - customerId - - name - - accessClientId - - createdAt - - updatedAt - additionalProperties: false - example: [] - count: - description: Total number of tokens returned - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - required: - - tokens - - count - additionalProperties: false - ProposalCardOutput: - description: Visual card data for rendering proposals in marketplace UI, following ADCP product card pattern - type: object - properties: - title: - description: Proposal name/title - example: Premium Display Campaign - type: string - description: - description: What the proposal offers - example: Target premium inventory at $2.50 vCPM with 85% viewability guarantee - type: string - image_carousel: - description: Optional array of image URLs showcasing the approach - example: - - https://example.com/chart1.png - - https://example.com/viz2.png - type: array - items: - type: string - format: uri - details: - description: Markdown-formatted detailed execution plan and specifications - example: |- - ## Execution Strategy - - We will target... - type: string - pricing_summary: - description: Pricing information for comparison - type: object - properties: - method: - description: Human-readable pricing method - example: 15% revenue share - type: string - budget_capacity: - description: Human-readable budget capacity - example: $50,000 maximum - type: string - estimated_cost: - description: Optional estimated cost calculation - example: $7,500 estimated fee - type: string - required: - - method - - budget_capacity - additionalProperties: false - required: - - title - - description - - pricing_summary - additionalProperties: false - BudgetRangeOutput: - description: Budget range for campaign planning - type: object - properties: - min: - description: Minimum budget available - example: 50000 - type: number - minimum: 0 - exclusiveMinimum: true - max: - description: Maximum budget available - example: 150000 - type: number - minimum: 0 - exclusiveMinimum: true - currency: - description: Currency for budget (ISO 4217 code) - example: USD - default: USD - type: string - minLength: 3 - maxLength: 3 - required: - - min - - max - - currency - additionalProperties: false - BrandAgentUpdateOutput: - type: object - properties: - id: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - manifestUrl: - type: string - format: uri - example: https://example.com - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - customerId - - createdAt - - updatedAt - additionalProperties: false - BrandStandardsCreateOutput: - type: object - properties: - id: - type: string - example: example_id_123 - name: - type: string - example: Example Name - description: - type: string - example: string - countryCodes: - type: array - items: - type: string - example: [] - channelCodes: - type: array - items: - type: string - example: [] - brands: - type: array - items: - type: string - example: [] - models: - type: array - items: - type: object - properties: - id: - type: string - name: - type: string - prompt: - type: string - status: - nullable: true - type: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - id - - name - - prompt - - status - - createdAt - - updatedAt - additionalProperties: false - example: [] - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - countryCodes - - channelCodes - - brands - - models - - createdAt - - updatedAt - additionalProperties: false - CampaignUpdateOutput: - type: object - properties: - campaignId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - status: - type: string - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - campaignId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - CreativeGetOutput: - type: object - properties: - creativeId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - status: - type: string - example: string - campaignId: - type: string - example: example_id_123 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - creativeId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - MediaBuyGetOutput: - type: object - properties: - id: - type: string - example: example_id_123 - tacticId: - type: number - example: 100 - customerId: - type: number - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - products: - type: array - items: - type: object - properties: - mediaProductId: - type: string - salesAgentId: - type: string - salesAgentName: - type: string - budgetAmount: - type: number - budgetCurrency: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - displayOrder: - type: number - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - mediaProductId - - salesAgentId - additionalProperties: false - example: [] - packages: - type: array - items: - type: object - properties: - packageId: - type: string - productIds: - type: array - items: - type: string - impressions: - type: number - budget: - type: number - targetingOverlay: {} - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - salesAgentId: - type: string - salesAgentName: - type: string - pricingCpm: - type: number - pricingSignalCost: - type: number - bidPrice: - type: number - pricingOptionId: - type: string - creativeFormats: - type: array - items: - type: object - properties: - agent_url: - type: string - id: - type: string - required: - - agent_url - - id - additionalProperties: false - required: - - packageId - - productIds - - impressions - - budget - - targetingOverlay - - creatives - - createdAt - - updatedAt - additionalProperties: false - example: [] - creatives: - type: array - items: - type: object - properties: - creativeId: - type: string - name: - type: string - formatId: - type: string - mediaUrl: - type: string - status: - type: string - required: - - creativeId - - name - - formatId - - mediaUrl - - status - additionalProperties: false - example: [] - pricing: - type: object - properties: - cpm: - type: number - signalCost: - type: number - totalCpm: - type: number - required: - - cpm - - totalCpm - additionalProperties: false - status: - type: string - example: string - adcp: - type: object - properties: - mediaBuyId: - type: string - status: - type: string - webhookUrl: - type: string - additionalProperties: false - performance: - type: object - properties: - impressions: - type: number - spend: - type: number - clicks: - type: number - lastUpdated: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - required: - - impressions - - spend - - clicks - additionalProperties: false - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - tacticId - - customerId - - name - - pricing - - status - - createdAt - - updatedAt - additionalProperties: false - TacticGetOutput: - type: object - properties: - id: - type: number - example: 100 - name: - type: string - example: Example Name - prompt: - type: string - example: string - campaignIds: - type: array - items: - type: string - example: [] - channelCodes: - type: array - items: - type: string - example: [] - countryCodes: - type: array - items: - type: string - example: [] - mediaBuyCount: - type: integer - minimum: 0 - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - archivedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - channelCodes - - countryCodes - - createdAt - - updatedAt - additionalProperties: false - BrandAgentGet: - type: object - properties: - id: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - manifestUrl: - type: string - format: uri - example: https://example.com - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - customerId - - createdAt - - updatedAt - additionalProperties: false - BrandAgentCreate: - type: object - properties: - id: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - name: - type: string - example: Example Name - description: - type: string - example: string - manifestUrl: - type: string - format: uri - example: https://example.com - customerId: - type: integer - exclusiveMinimum: true - maximum: 9007199254740991 - example: 100 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - id - - name - - customerId - - createdAt - - updatedAt - additionalProperties: false - CampaignCreate: - type: object - properties: - campaignId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - status: - type: string - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - campaignId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - CampaignGet: - type: object - properties: - campaignId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - status: - type: string - example: string - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - campaignId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - CreativeCreate: - type: object - properties: - creativeId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - status: - type: string - example: string - campaignId: - type: string - example: example_id_123 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - creativeId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - CreativeUpdate: - type: object - properties: - creativeId: - type: string - example: example_id_123 - name: - type: string - example: Example Name - status: - type: string - example: string - campaignId: - type: string - example: example_id_123 - createdAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - updatedAt: - type: string - format: date-time - pattern: >- - ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ - example: string - required: - - creativeId - - name - - status - - createdAt - - updatedAt - additionalProperties: false - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT diff --git a/scripts/README.md b/scripts/README.md index e382988..2936fb7 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,114 +1,46 @@ -# Scope3 CLI Workflow Scripts +# Scope3 SDK v2 - Test Scripts -This directory contains end-to-end workflow test scripts for the Scope3 CLI tool. +Manual workflow tests for the Scope3 SDK. Each script exercises real API calls against production or staging. -## ๐ŸŽฏ Platform vs Partner Access - -Scope3 has two levels of API access: - -- **Platform API** - Create/manage brand agents, campaigns, creatives; read-only access to tactics and media buys -- **Partner API** - Full access to create/manage tactics, media buys, and execute campaigns - -**Use the appropriate workflow for your access level!** - -## Available Scripts - -### `platform-workflow-test.sh` - Platform Workflow Test - -**For platform users with platform-level API keys** - -Demonstrates complete platform workflow: -- โœ… Create and manage brand agents -- โœ… Create and manage campaigns -- โœ… Discover marketplace agents and products -- โœ… View tactics and media buys (read-only) -- โœ… Manage notifications - -**Usage:** - -```bash -# Set your platform API key -export SCOPE3_API_KEY=your_platform_api_key - -# Run the platform workflow test -./scripts/platform-workflow-test.sh -``` - -**Expected output:** -``` -========================================== - PLATFORM WORKFLOW TEST -========================================== - -โœ“ Channels discovered (12 channels) -โœ“ Brand agent created (ID: 3167) -โœ“ Campaign created (ID: campaign_xxx) -โœ“ Marketplace agents discovered -โœ“ Tactics viewed (read-only) -โœ“ Media buys viewed (read-only) - -โœ… Platform workflow test successful! -``` - -### `partner-workflow-test.sh` - Partner Workflow Test - -**For partners with partner-level API keys** - -Demonstrates complete partner workflow: -- โœ… Register and manage sales/outcome agents -- โœ… Create and manage tactics -- โœ… Create and manage media buys -- โœ… Execute campaigns -- โœ… Sync products - -**Usage:** +## Setup ```bash -# Set your partner API key -export SCOPE3_API_KEY=your_partner_api_key - -# Run the partner workflow test -./scripts/partner-workflow-test.sh +npm run build # build the SDK + CLI first +export SCOPE3_API_KEY=your_api_key # get from agentic.scope3.com -> Manage API Keys ``` -**Note:** If you have a platform key and try to run this, it will show warnings explaining that partner operations require elevated permissions. +## Scripts -## Quick Start +| Script | Persona | What it tests | +|--------|---------|---------------| +| `test-buyer-workflow.sh` | buyer | Advertisers, bundles, product discovery, campaigns | +| `test-brand-workflow.sh` | brand | Brand CRUD with manifest URL and inline JSON | +| `test-partner-workflow.sh` | partner | Health check, config, skill.md | +| `test-sdk-workflow.ts` | all 3 | Full TypeScript SDK test (not CLI) | -### If you're a Platform User (Most Common) +## Usage ```bash -export SCOPE3_API_KEY=your_key -./scripts/platform-workflow-test.sh +# CLI workflow tests (bash) +./scripts/test-buyer-workflow.sh +./scripts/test-brand-workflow.sh +./scripts/test-partner-workflow.sh + +# Use staging +./scripts/test-buyer-workflow.sh --staging + +# TypeScript SDK test (all personas) +npx ts-node scripts/test-sdk-workflow.ts +npx ts-node scripts/test-sdk-workflow.ts --staging + +# Or via npm scripts +npm run test:buyer +npm run test:brand +npm run test:partner +npm run test:sdk +npm run test:all # runs all 4 ``` -### If you're a Partner - -```bash -export SCOPE3_API_KEY=your_partner_key -./scripts/partner-workflow-test.sh -``` - -### If you're unsure - -Run the platform workflow first. If you get permission errors on tactics/media buys **creation** (viewing is OK), you have platform access. - -## What Each Workflow Tests - -| Operation | Platform | Partner | -|-----------|----------|---------| -| List Channels | โœ… | โœ… | -| Create Brand Agents | โœ… | โœ… | -| Create Campaigns | โœ… | โœ… | -| Register Agents | โŒ | โœ… | -| Create Tactics | โŒ | โœ… | -| Create Media Buys | โŒ | โœ… | -| View Tactics | โœ… (read-only) | โœ… | -| View Media Buys | โœ… (read-only) | โœ… | -| Discover Marketplace | โœ… | โœ… | - -## See Also +## Cleanup -- **CLI Documentation**: See `../CLI.md` for complete CLI reference -- **Workflow Guide**: See `../WORKFLOW_GUIDE.md` for detailed explanation of platform vs partner roles -- **Status Report**: See `../CLI_STATUS.md` for current status of all operations +The buyer and brand scripts auto-clean test resources on exit. If a script is interrupted, check your dashboard for leftover test advertisers/brands. diff --git a/scripts/generate-sdk.ts b/scripts/generate-sdk.ts deleted file mode 100644 index 5569935..0000000 --- a/scripts/generate-sdk.ts +++ /dev/null @@ -1,346 +0,0 @@ -#!/usr/bin/env ts-node -/** - * Generates TypeScript SDK clients from OpenAPI specifications - * - * This script reads OpenAPI YAML files and generates: - * - PlatformClient from platform-api.yaml (for brand advertisers/buyers) - * - PartnerClient from partner-api.yaml (for DSPs/publishers/partners) - * - * Generated clients wrap MCP tool calls with typed methods. - */ - -import * as fs from 'fs'; -import * as path from 'path'; -import * as yaml from 'js-yaml'; - -interface OpenAPISpec { - info: { - title: string; - description: string; - }; - paths: Record>; - components?: { - schemas?: Record; - }; -} - -interface Operation { - operationId: string; - summary?: string; - description?: string; - tags?: string[]; - requestBody?: { - content: { - 'application/json': { - schema: { - $ref?: string; - type?: string; - properties?: Record; - required?: string[]; - }; - }; - }; - }; - responses?: Record; -} - -interface ResourceGroup { - name: string; - operations: Array<{ - operationId: string; - methodName: string; - summary?: string; - description?: string; - hasParams: boolean; - }>; -} - -function parseOpenAPISpec(filePath: string): OpenAPISpec { - const content = fs.readFileSync(filePath, 'utf-8'); - return yaml.load(content) as OpenAPISpec; -} - -function operationIdToMethodName(operationId: string, resourceName: string): string { - // Convert snake_case operation IDs to camelCase method names - // e.g., "brand_agent_list" on brandAgents resource -> "list" - // e.g., "country_list" on targeting resource -> "countryList" - // e.g., "tactic_link_campaign" on tactics resource -> "linkCampaign" - - const parts = operationId.split('_'); - - // Convert resourceName to snake_case to match against operation ID - // "brandAgents" -> "brand_agent", "mediaBuys" -> "media_buy" - const resourceSnakeCase = resourceName - .replace(/([A-Z])/g, '_$1') - .toLowerCase() - .replace(/^_/, '') - .replace(/s$/, ''); // Remove trailing 's' for plural resources - - const resourceParts = resourceSnakeCase.split('_'); - - // Check if operation ID starts with the resource name - // e.g., "brand_agent_list" starts with ["brand", "agent"] - let skipParts = 0; - for (let i = 0; i < resourceParts.length && i < parts.length; i++) { - if (parts[i] === resourceParts[i]) { - skipParts++; - } else { - break; - } - } - - // If we matched the resource prefix, skip it - const methodParts = skipParts > 0 ? parts.slice(skipParts) : parts; - - // Convert to camelCase - return methodParts.map((part, i) => - i === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1) - ).join(''); -} - -function toCamelCase(str: string): string { - // Convert "Brand Agents" or "brand_agents" to "brandAgents" - return str - .split(/[\s_-]+/) - .map((word, index) => - index === 0 - ? word.toLowerCase() - : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase() - ) - .join(''); -} - -function groupOperationsByResource(spec: OpenAPISpec): Map { - const groups = new Map(); - - for (const [path, methods] of Object.entries(spec.paths)) { - for (const [method, operation] of Object.entries(methods)) { - if (method !== 'post' || !operation.operationId) continue; - - // Skip mcp-initialize, it's handled by the base client - if (operation.operationId === 'mcp_initialize') continue; - - // Extract resource name from operation ID or tags - // e.g., "brand_agent_list" -> "brandAgents" - const operationId = operation.operationId; - let resourceName: string; - - if (operation.tags && operation.tags.length > 0) { - // Use tag as resource name, convert to camelCase - resourceName = toCamelCase(operation.tags[0]); - } else { - // Extract from operation ID - const parts = operationId.split('_'); - // Find the action word index - const actionIndex = parts.findIndex(p => - ['list', 'get', 'create', 'update', 'delete', 'execute', 'sync', 'validate', 'discover', 'save', 'mark'].includes(p) - ); - - if (actionIndex > 0) { - // Resource name is everything before the action - const resourceParts = parts.slice(0, actionIndex); - resourceName = toCamelCase(resourceParts.join('_')); - } else { - // Default to first part - resourceName = toCamelCase(parts[0]); - } - } - - if (!groups.has(resourceName)) { - groups.set(resourceName, { - name: resourceName, - operations: [], - }); - } - - const hasParams = !!(operation.requestBody?.content['application/json']?.schema); - - groups.get(resourceName)!.operations.push({ - operationId, - methodName: operationIdToMethodName(operationId, resourceName), - summary: operation.summary, - description: operation.description, - hasParams, - }); - } - } - - return groups; -} - -function generateResourceClass(resource: ResourceGroup, typesImport: string): string { - const className = `${resource.name.charAt(0).toUpperCase()}${resource.name.slice(1)}Resource`; - - let code = `import { Scope3Client } from '../../client';\n`; - code += `import type { operations } from '../../types/${typesImport}';\n\n`; - - code += `export class ${className} {\n`; - code += ` constructor(private client: Scope3Client) {}\n\n`; - - for (const op of resource.operations) { - // Generate JSDoc comment - if (op.summary || op.description) { - code += ` /**\n`; - if (op.summary) { - code += ` * ${op.summary}\n`; - } - if (op.description && op.description !== op.summary) { - code += ` * ${op.description.split('\n').join('\n * ')}\n`; - } - code += ` */\n`; - } - - // Generate method signature - const paramsType = op.hasParams - ? `operations['${op.operationId}']['requestBody']['content']['application/json']` - : '{}'; - - const responseType = `operations['${op.operationId}']['responses'][200]['content']['application/json']`; - - if (op.hasParams) { - code += ` async ${op.methodName}(params: ${paramsType}): Promise<${responseType}> {\n`; - code += ` return this.client['callTool']('${op.operationId}', params);\n`; - } else { - code += ` async ${op.methodName}(): Promise<${responseType}> {\n`; - code += ` return this.client['callTool']('${op.operationId}', {});\n`; - } - code += ` }\n\n`; - } - - code += `}\n`; - - return code; -} - -function generateClientClass( - clientName: string, - apiTitle: string, - apiDescription: string, - resources: ResourceGroup[], - typesImport: string -): string { - let code = `import { Scope3Client } from './client';\n`; - code += `import { ClientConfig } from './types';\n`; - - // Import all resource classes - const clientDir = clientName.replace('Client', '').toLowerCase(); // "PlatformClient" -> "platform" - for (const resource of resources) { - const className = `${resource.name.charAt(0).toUpperCase()}${resource.name.slice(1)}Resource`; - code += `import { ${className} } from './resources/${clientDir}/${resource.name}';\n`; - } - - code += `\n`; - code += `/**\n`; - code += ` * ${apiTitle}\n`; - code += ` * \n`; - code += ` * ${apiDescription.split('\n').join('\n * ')}\n`; - code += ` */\n`; - code += `export class ${clientName} extends Scope3Client {\n`; - - // Declare resource properties - for (const resource of resources) { - const className = `${resource.name.charAt(0).toUpperCase()}${resource.name.slice(1)}Resource`; - code += ` public readonly ${resource.name}: ${className};\n`; - } - - code += `\n`; - code += ` constructor(config: ClientConfig) {\n`; - code += ` super(config);\n\n`; - - // Initialize resources - for (const resource of resources) { - const className = `${resource.name.charAt(0).toUpperCase()}${resource.name.slice(1)}Resource`; - code += ` this.${resource.name} = new ${className}(this);\n`; - } - - code += ` }\n\n`; - - // Add CLI support methods - code += ` // Expose MCP methods for CLI dynamic command generation\n`; - code += ` async listTools(): Promise {\n`; - code += ` if (!this.getClient()) {\n`; - code += ` await this.connect();\n`; - code += ` }\n`; - code += ` return this.getClient().listTools();\n`; - code += ` }\n\n`; - - code += ` async callTool, TResponse = unknown>(\n`; - code += ` toolName: string,\n`; - code += ` args: TRequest\n`; - code += ` ): Promise {\n`; - code += ` return super.callTool(toolName, args);\n`; - code += ` }\n`; - - code += `}\n`; - - return code; -} - -function main() { - const projectRoot = path.join(__dirname, '..'); - - // Parse OpenAPI specs - console.log('๐Ÿ“– Parsing OpenAPI specifications...'); - const platformSpec = parseOpenAPISpec(path.join(projectRoot, 'platform-api.yaml')); - const partnerSpec = parseOpenAPISpec(path.join(projectRoot, 'partner-api.yaml')); - - // Group operations by resource - console.log('๐Ÿ” Analyzing API operations...'); - const platformResources = Array.from(groupOperationsByResource(platformSpec).values()); - const partnerResources = Array.from(groupOperationsByResource(partnerSpec).values()); - - console.log(` Platform API: ${platformResources.length} resource groups`); - console.log(` Partner API: ${partnerResources.length} resource groups`); - - // Create output directories - const platformResourcesDir = path.join(projectRoot, 'src/resources/platform'); - const partnerResourcesDir = path.join(projectRoot, 'src/resources/partner'); - - fs.mkdirSync(platformResourcesDir, { recursive: true }); - fs.mkdirSync(partnerResourcesDir, { recursive: true }); - - // Generate Platform resources - console.log('\n๐Ÿ—๏ธ Generating Platform API resources...'); - for (const resource of platformResources) { - const code = generateResourceClass(resource, 'platform-api'); - const filePath = path.join(platformResourcesDir, `${resource.name}.ts`); - fs.writeFileSync(filePath, code); - console.log(` โœ“ ${resource.name} (${resource.operations.length} operations)`); - } - - // Generate Partner resources - console.log('\n๐Ÿ—๏ธ Generating Partner API resources...'); - for (const resource of partnerResources) { - const code = generateResourceClass(resource, 'partner-api'); - const filePath = path.join(partnerResourcesDir, `${resource.name}.ts`); - fs.writeFileSync(filePath, code); - console.log(` โœ“ ${resource.name} (${resource.operations.length} operations)`); - } - - // Generate client classes - console.log('\n๐ŸŽฏ Generating client classes...'); - - const platformClient = generateClientClass( - 'PlatformClient', - platformSpec.info.title, - platformSpec.info.description, - platformResources, - 'platform-api' - ); - fs.writeFileSync(path.join(projectRoot, 'src/platform-client.ts'), platformClient); - console.log(' โœ“ PlatformClient'); - - const partnerClient = generateClientClass( - 'PartnerClient', - partnerSpec.info.title, - partnerSpec.info.description, - partnerResources, - 'partner-api' - ); - fs.writeFileSync(path.join(projectRoot, 'src/partner-client.ts'), partnerClient); - console.log(' โœ“ PartnerClient'); - - console.log('\nโœ… SDK generation complete!'); -} - -main(); diff --git a/scripts/partner-workflow-test.sh b/scripts/partner-workflow-test.sh deleted file mode 100755 index d6bce9b..0000000 --- a/scripts/partner-workflow-test.sh +++ /dev/null @@ -1,290 +0,0 @@ -#!/bin/bash - -# Scope3 CLI - Partner Workflow Test -# Tests operations available to partners (sales/outcome agents, tactics, media buys) - -set -e # Exit on error - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Configuration -CLI_CMD="node dist/cli.js" -OUTPUT_FORMAT="json" - -# Function to print colored output -print_step() { - echo -e "${BLUE}==>${NC} ${1}" -} - -print_success() { - echo -e "${GREEN}โœ“${NC} ${1}" -} - -print_error() { - echo -e "${RED}โœ—${NC} ${1}" -} - -print_warning() { - echo -e "${YELLOW}โš ${NC} ${1}" -} - -print_info() { - echo -e "${BLUE}โ„น${NC} ${1}" -} - -# Check if API key is set -if [ -z "$SCOPE3_API_KEY" ]; then - print_error "SCOPE3_API_KEY environment variable is not set" - echo "Please set it with: export SCOPE3_API_KEY=your_partner_api_key" - exit 1 -fi - -print_success "API key found" -echo "" -echo "==========================================" -echo " PARTNER WORKFLOW TEST" -echo "==========================================" -echo "" -echo "This test demonstrates partner-level operations:" -echo "โœ“ Register and manage sales/outcome agents" -echo "โœ“ Create and manage tactics" -echo "โœ“ Create and manage media buys" -echo "โœ“ Execute campaign via agents" -echo "" -print_warning "NOTE: This workflow requires a PARTNER-level API key" -print_info "If you have a platform key, use platform-workflow-test.sh instead" -echo "" - -# Step 1: List Existing Agents -print_step "Step 1: Listing Registered Agents..." -AGENTS_RESPONSE=$($CLI_CMD agent list --format $OUTPUT_FORMAT 2>&1) -if [ $? -eq 0 ]; then - print_success "Agents listed successfully" - echo "$AGENTS_RESPONSE" | head -20 -else - print_warning "Failed to list agents" -fi -echo "" - -# Step 2: Register Sales Agent (Partner Operation) -print_step "Step 2: Registering Sales Agent..." -print_info "Attempting to register a sales agent (partner operation)" -SALES_AGENT_RESPONSE=$($CLI_CMD agent register \ - --type SALES \ - --name "Partner Test Sales Agent $(date +%s)" \ - --endpointUrl "https://example.com/sales-agent/mcp" \ - --protocol MCP \ - --format $OUTPUT_FORMAT 2>&1) - -if [ $? -eq 0 ]; then - print_success "Sales agent registered" - SALES_AGENT_ID=$(echo "$SALES_AGENT_RESPONSE" | grep -o '"agentId":"[^"]*"' | head -1 | sed 's/"agentId":"//' | sed 's/"//') - echo "Sales Agent ID: $SALES_AGENT_ID" -else - print_warning "Failed to register sales agent (requires partner access)" - echo "$SALES_AGENT_RESPONSE" - SALES_AGENT_ID="" -fi -echo "" - -# Step 3: Register Outcome Agent (Partner Operation) -print_step "Step 3: Registering Outcome Agent..." -print_info "Attempting to register an outcome agent (partner operation)" -OUTCOME_AGENT_RESPONSE=$($CLI_CMD agent register \ - --type OUTCOME \ - --name "Partner Test Outcome Agent $(date +%s)" \ - --endpointUrl "https://example.com/outcome-agent/mcp" \ - --protocol MCP \ - --format $OUTPUT_FORMAT 2>&1) - -if [ $? -eq 0 ]; then - print_success "Outcome agent registered" - OUTCOME_AGENT_ID=$(echo "$OUTCOME_AGENT_RESPONSE" | grep -o '"agentId":"[^"]*"' | head -1 | sed 's/"agentId":"//' | sed 's/"//') - echo "Outcome Agent ID: $OUTCOME_AGENT_ID" -else - print_warning "Failed to register outcome agent (requires partner access)" - echo "$OUTCOME_AGENT_RESPONSE" - OUTCOME_AGENT_ID="" -fi -echo "" - -# Step 4: Get Existing Campaign for Testing -print_step "Step 4: Finding Existing Campaign..." -CAMPAIGNS_RESPONSE=$($CLI_CMD campaign list --format $OUTPUT_FORMAT 2>&1) -if [ $? -eq 0 ]; then - print_success "Campaigns retrieved" - # Try to extract first campaign ID - CAMPAIGN_ID=$(echo "$CAMPAIGNS_RESPONSE" | grep -o 'campaign_[a-zA-Z0-9_]*' | head -1) - if [ -n "$CAMPAIGN_ID" ]; then - echo "Using existing campaign: $CAMPAIGN_ID" - else - print_warning "No campaign found. Create one first with buyer workflow." - CAMPAIGN_ID="" - fi -else - print_warning "Failed to list campaigns" - CAMPAIGN_ID="" -fi -echo "" - -# Step 5: Create Tactic (Partner Operation) -if [ -n "$CAMPAIGN_ID" ]; then - print_step "Step 5: Creating Tactic (Partner Operation)..." - print_info "Attempting to create a tactic (requires partner access)" - TACTIC_RESPONSE=$($CLI_CMD tactic create \ - --name "Partner Test Tactic $(date +%s)" \ - --campaignId "$CAMPAIGN_ID" \ - --prompt "Focus on high-impact video placements" \ - --channelCodes video,display \ - --format $OUTPUT_FORMAT 2>&1) - - if [ $? -eq 0 ]; then - print_success "Tactic created" - TACTIC_ID=$(echo "$TACTIC_RESPONSE" | grep -o '"tacticId":"[^"]*"' | head -1 | sed 's/"tacticId":"//' | sed 's/"//') - if [ -z "$TACTIC_ID" ]; then - TACTIC_ID=$(echo "$TACTIC_RESPONSE" | grep -o 'tactic_[a-zA-Z0-9_]*' | head -1) - fi - echo "Tactic ID: $TACTIC_ID" - else - print_warning "Failed to create tactic (requires partner access)" - echo "$TACTIC_RESPONSE" - TACTIC_ID="" - fi -else - print_warning "Step 5: Skipping tactic creation (no campaign available)" - TACTIC_ID="" -fi -echo "" - -# Step 6: List Tactics -print_step "Step 6: Listing All Tactics..." -$CLI_CMD tactic list --format $OUTPUT_FORMAT > /dev/null 2>&1 -if [ $? -eq 0 ]; then - print_success "Tactics listed successfully" -else - print_warning "Failed to list tactics" -fi -echo "" - -# Step 7: Create Media Buy (Partner Operation) -if [ -n "$TACTIC_ID" ] && [ -n "$SALES_AGENT_ID" ]; then - print_step "Step 7: Creating Media Buy (Partner Operation)..." - print_info "Attempting to create a media buy (requires partner access)" - MEDIA_BUY_RESPONSE=$($CLI_CMD media-buy create \ - --tacticId "$TACTIC_ID" \ - --name "Partner Test Media Buy" \ - --media-product '[{"mediaProductId":"prod-123","salesAgentId":"'$SALES_AGENT_ID'"}]' \ - --budget '{"amount":50000,"currency":"USD"}' \ - --format $OUTPUT_FORMAT 2>&1) - - if [ $? -eq 0 ]; then - print_success "Media buy created" - MEDIA_BUY_ID=$(echo "$MEDIA_BUY_RESPONSE" | grep -o '"mediaBuyId":"[^"]*"' | head -1 | sed 's/"mediaBuyId":"//' | sed 's/"//') - echo "Media Buy ID: $MEDIA_BUY_ID" - else - print_warning "Failed to create media buy (requires partner access and valid products)" - echo "$MEDIA_BUY_RESPONSE" - MEDIA_BUY_ID="" - fi -else - print_warning "Step 7: Skipping media buy creation (missing tactic or sales agent)" - MEDIA_BUY_ID="" -fi -echo "" - -# Step 8: List Media Buys -print_step "Step 8: Listing All Media Buys..." -$CLI_CMD media-buy list --format $OUTPUT_FORMAT > /dev/null 2>&1 -if [ $? -eq 0 ]; then - print_success "Media buys listed successfully" -else - print_warning "Failed to list media buys" -fi -echo "" - -# Step 9: Execute Media Buy (Partner Operation) -if [ -n "$MEDIA_BUY_ID" ]; then - print_step "Step 9: Executing Media Buy (Partner Operation)..." - print_info "Attempting to execute media buy" - EXECUTE_RESPONSE=$($CLI_CMD media-buy execute \ - --mediaBuyId "$MEDIA_BUY_ID" \ - --format $OUTPUT_FORMAT 2>&1) - - if [ $? -eq 0 ]; then - print_success "Media buy executed successfully" - else - print_warning "Failed to execute media buy" - echo "$EXECUTE_RESPONSE" - fi -else - print_warning "Step 9: Skipping media buy execution (no media buy created)" -fi -echo "" - -# Step 10: Sync Products (Partner Operation) -if [ -n "$SALES_AGENT_ID" ]; then - print_step "Step 10: Syncing Products from Sales Agent..." - SYNC_RESPONSE=$($CLI_CMD media-product sync \ - --salesAgentId "$SALES_AGENT_ID" \ - --format $OUTPUT_FORMAT 2>&1) - - if [ $? -eq 0 ]; then - print_success "Products synced successfully" - else - print_warning "Failed to sync products" - fi -else - print_warning "Step 10: Skipping product sync (no sales agent registered)" -fi -echo "" - -# Summary -echo "" -echo "==========================================" -echo " PARTNER WORKFLOW SUMMARY" -echo "==========================================" -echo "" - -if [ -n "$SALES_AGENT_ID" ] || [ -n "$OUTCOME_AGENT_ID" ] || [ -n "$TACTIC_ID" ] || [ -n "$MEDIA_BUY_ID" ]; then - print_success "Partner operations executed!" - echo "" - echo "โœ… Created Resources:" - [ -n "$SALES_AGENT_ID" ] && echo " โ€ข Sales Agent ID: $SALES_AGENT_ID" - [ -n "$OUTCOME_AGENT_ID" ] && echo " โ€ข Outcome Agent ID: $OUTCOME_AGENT_ID" - [ -n "$TACTIC_ID" ] && echo " โ€ข Tactic ID: $TACTIC_ID" - [ -n "$MEDIA_BUY_ID" ] && echo " โ€ข Media Buy ID: $MEDIA_BUY_ID" - echo "" - echo "โœ… Partner Capabilities Verified:" - echo " โ€ข Register and manage sales/outcome agents" - echo " โ€ข Create and manage tactics" - echo " โ€ข Create and manage media buys" - echo " โ€ข Execute campaigns" - echo "" - echo "๐Ÿ“‹ To clean up test resources:" - [ -n "$MEDIA_BUY_ID" ] && echo " $CLI_CMD media-buy delete --mediaBuyId $MEDIA_BUY_ID" - [ -n "$TACTIC_ID" ] && echo " $CLI_CMD tactic delete --tacticId $TACTIC_ID" - [ -n "$SALES_AGENT_ID" ] && echo " $CLI_CMD agent unregister --agentId $SALES_AGENT_ID" - [ -n "$OUTCOME_AGENT_ID" ] && echo " $CLI_CMD agent unregister --agentId $OUTCOME_AGENT_ID" - echo "" - print_success "Partner workflow test successful!" -else - print_warning "No partner operations succeeded" - echo "" - echo "โŒ Partner Operations Failed:" - echo " โ€ข Could not register agents" - echo " โ€ข Could not create tactics" - echo " โ€ข Could not create media buys" - echo "" - print_info "Possible Reasons:" - echo " 1. API key does not have partner-level permissions" - echo " 2. Using a buyer-level API key instead of partner key" - echo " 3. Missing required configuration or setup" - echo "" - print_info "If you are a PLATFORM (not a partner), use platform-workflow-test.sh instead" - echo "" -fi diff --git a/scripts/platform-workflow-test.sh b/scripts/platform-workflow-test.sh deleted file mode 100755 index a5e426a..0000000 --- a/scripts/platform-workflow-test.sh +++ /dev/null @@ -1,229 +0,0 @@ -#!/bin/bash - -# Scope3 CLI - Platform Workflow Test -# Tests operations available to platform users (brand agents, campaigns, creatives, discovery) - -set -e # Exit on error - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Configuration -CLI_CMD="node dist/cli.js" -OUTPUT_FORMAT="json" - -# Function to print colored output -print_step() { - echo -e "${BLUE}==>${NC} ${1}" -} - -print_success() { - echo -e "${GREEN}โœ“${NC} ${1}" -} - -print_error() { - echo -e "${RED}โœ—${NC} ${1}" -} - -print_warning() { - echo -e "${YELLOW}โš ${NC} ${1}" -} - -# Function to extract value from JSON using basic tools -extract_json_value() { - local json=$1 - local key=$2 - echo "$json" | grep -o "\"$key\":[^,}]*" | head -1 | sed 's/.*: *"\?\([^"]*\)"\?.*/\1/' | sed 's/[^a-zA-Z0-9_-]//g' -} - -# Check if API key is set -if [ -z "$SCOPE3_API_KEY" ]; then - print_error "SCOPE3_API_KEY environment variable is not set" - echo "Please set it with: export SCOPE3_API_KEY=your_api_key" - exit 1 -fi - -print_success "API key found" -echo "" -echo "==========================================" -echo " PLATFORM WORKFLOW TEST" -echo "==========================================" -echo "" -echo "This test demonstrates platform-level operations:" -echo "โœ“ Brand agent management" -echo "โœ“ Campaign creation and management" -echo "โœ“ Marketplace discovery" -echo "โœ“ Read-only access to tactic and media buys" -echo "" - -# Step 1: List available channels -print_step "Step 1: Discovering Available Channels..." -CHANNELS_RESPONSE=$($CLI_CMD channel list --format $OUTPUT_FORMAT 2>&1) -if [ $? -eq 0 ]; then - print_success "Channels discovered" - echo "Available channels: display, ctv, video, audio, social, dooh, etc." -else - print_error "Failed to list channels" - echo "$CHANNELS_RESPONSE" - exit 1 -fi -echo "" - -# Step 2: Create Brand Agent -print_step "Step 2: Creating Brand Agent..." -BRAND_AGENT_RESPONSE=$($CLI_CMD brand-agent create \ - --name "Test Platform Agent $(date +%s)" \ - --description "Automated platform workflow test" \ - --manifestUrl "https://example.com/manifest.json" \ - --format $OUTPUT_FORMAT 2>&1) - -if [ $? -eq 0 ]; then - print_success "Brand agent created" - BRAND_AGENT_ID=$(echo "$BRAND_AGENT_RESPONSE" | grep -o '"id":[0-9]*' | head -1 | sed 's/"id"://') - if [ -z "$BRAND_AGENT_ID" ]; then - BRAND_AGENT_ID=$(echo "$BRAND_AGENT_RESPONSE" | grep -o 'ID: [0-9]*' | head -1 | sed 's/ID: //') - fi - echo "Brand Agent ID: $BRAND_AGENT_ID" -else - print_error "Failed to create brand agent" - echo "$BRAND_AGENT_RESPONSE" - exit 1 -fi -echo "" - -# Step 3: List Brand Agents -print_step "Step 3: Verifying Brand Agent in List..." -$CLI_CMD brand-agent list --format $OUTPUT_FORMAT > /dev/null 2>&1 -if [ $? -eq 0 ]; then - print_success "Brand agent listed successfully" -else - print_warning "Failed to list brand agents" -fi -echo "" - -# Step 4: Create Campaign -print_step "Step 4: Creating Campaign..." -CAMPAIGN_RESPONSE=$($CLI_CMD campaign create \ - --prompt "Q1 2024 awareness campaign targeting eco-conscious millennials across digital channels with focus on video and social media" \ - --brandAgentId "$BRAND_AGENT_ID" \ - --name "Buyer Test Campaign $(date +%s)" \ - --format $OUTPUT_FORMAT 2>&1) - -if [ $? -eq 0 ]; then - print_success "Campaign created" - CAMPAIGN_ID=$(echo "$CAMPAIGN_RESPONSE" | grep -o 'campaign_[a-zA-Z0-9_]*' | head -1) - echo "Campaign ID: $CAMPAIGN_ID" -else - print_error "Failed to create campaign" - echo "$CAMPAIGN_RESPONSE" - exit 1 -fi -echo "" - -# Step 5: List Campaigns -print_step "Step 5: Listing All Campaigns..." -$CLI_CMD campaign list --format $OUTPUT_FORMAT > /dev/null 2>&1 -if [ $? -eq 0 ]; then - print_success "Campaigns listed successfully" -else - print_warning "Failed to list campaigns" -fi -echo "" - -# Step 6: Get Campaign Summary -print_step "Step 6: Getting Campaign Summary..." -SUMMARY_RESPONSE=$($CLI_CMD campaign-get summary --campaignId "$CAMPAIGN_ID" --format $OUTPUT_FORMAT 2>&1) -if [ $? -eq 0 ]; then - print_success "Campaign summary retrieved" -else - print_warning "Failed to get campaign summary (may need time for data)" -fi -echo "" - -# Step 7: Discover Marketplace Agents -print_step "Step 7: Discovering Marketplace Agents..." -AGENTS_RESPONSE=$($CLI_CMD agent list --format $OUTPUT_FORMAT 2>&1) -if [ $? -eq 0 ]; then - print_success "Marketplace agent discovered" - echo "Found sales agent available for partnerships" -else - print_warning "Failed to discover agents" -fi -echo "" - -# Step 8: Discover Media Products -print_step "Step 8: Discovering Available Media Products..." -PRODUCTS_RESPONSE=$($CLI_CMD media-product discover --format $OUTPUT_FORMAT 2>&1) -if [ $? -eq 0 ]; then - print_success "Media media-product discovered" - echo "Found available inventory from sales agents" -else - print_warning "Failed to discover media-product (may require registered sales agents)" -fi -echo "" - -# Step 9: View Tactics (Read-Only) -print_step "Step 9: Viewing Tactics (Read-Only Access)..." -print_warning "Note: Platform users can only READ tactics, not create them" -TACTICS_RESPONSE=$($CLI_CMD tactic list --format $OUTPUT_FORMAT 2>&1) -if [ $? -eq 0 ]; then - print_success "Tactics viewed successfully (read-only)" -else - print_warning "No tactic available or access denied" -fi -echo "" - -# Step 10: View Media Buys (Read-Only) -print_step "Step 10: Viewing Media Buys (Read-Only Access)..." -print_warning "Note: Platform users can only READ media buys, not create them" -MEDIA_BUYS_RESPONSE=$($CLI_CMD media-buy list --format $OUTPUT_FORMAT 2>&1) -if [ $? -eq 0 ]; then - print_success "Media buys viewed successfully (read-only)" -else - print_warning "No media buys available or access denied" -fi -echo "" - -# Step 11: Check Notifications -print_step "Step 11: Checking Notifications..." -$CLI_CMD notifications list --limit 5 --format $OUTPUT_FORMAT > /dev/null 2>&1 -if [ $? -eq 0 ]; then - print_success "Notifications retrieved" -else - print_warning "Failed to list notifications" -fi -echo "" - -# Summary -echo "" -echo "==========================================" -echo " PLATFORM WORKFLOW SUMMARY" -echo "==========================================" -echo "" -print_success "Buyer workflow test completed!" -echo "" -echo "โœ… Created Resources:" -echo " โ€ข Brand Agent ID: $BRAND_AGENT_ID" -echo " โ€ข Campaign ID: $CAMPAIGN_ID" -echo "" -echo "โœ… Buyer Capabilities Verified:" -echo " โ€ข Create and manage brand agents" -echo " โ€ข Create and manage campaigns" -echo " โ€ข Discover marketplace agent and products" -echo " โ€ข View tactic and media buys (read-only)" -echo " โ€ข Manage notifications" -echo "" -echo "โ„น๏ธ Buyer Limitations:" -echo " โ€ข Cannot create tactic (partner operation)" -echo " โ€ข Cannot create media buys (partner operation)" -echo " โ€ข Cannot execute campaign directly (requires partner agents)" -echo "" -echo "๐Ÿ“‹ To clean up test resources:" -echo " $CLI_CMD campaign delete --campaignId $CAMPAIGN_ID" -echo " $CLI_CMD brand-agent delete --brandAgentId $BRAND_AGENT_ID" -echo "" -print_success "Buyer workflow test successful!" diff --git a/scripts/test-brand-workflow.sh b/scripts/test-brand-workflow.sh new file mode 100755 index 0000000..a5bfed2 --- /dev/null +++ b/scripts/test-brand-workflow.sh @@ -0,0 +1,116 @@ +#!/bin/bash + +# Scope3 SDK v2 - Brand Workflow Test +# Tests the brand persona flow: list, create, update, delete brands +# +# Usage: +# export SCOPE3_API_KEY=your_brand_api_key +# ./scripts/test-brand-workflow.sh +# ./scripts/test-brand-workflow.sh --staging + +set -euo pipefail + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +CLI="node dist/cli/index.js --persona brand --format json" +CREATED_BRAND_ID="" +STEP=0 + +if [[ "${1:-}" == "--staging" ]]; then + CLI="$CLI --environment staging" + echo -e "${YELLOW}Using STAGING environment${NC}" +fi + +step() { STEP=$((STEP + 1)); echo -e "\n${BLUE}[$STEP]${NC} $1"; } +pass() { echo -e " ${GREEN}PASS${NC} $1"; } +fail() { echo -e " ${RED}FAIL${NC} $1"; } +warn() { echo -e " ${YELLOW}SKIP${NC} $1"; } +extract() { node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(eval('d.$1'));" 2>/dev/null; } + +cleanup() { + echo -e "\n${BLUE}Cleanup${NC}" + if [ -n "$CREATED_BRAND_ID" ]; then + $CLI brands delete "$CREATED_BRAND_ID" > /dev/null 2>&1 && \ + pass "Deleted brand $CREATED_BRAND_ID" || \ + warn "Could not delete brand $CREATED_BRAND_ID" + fi +} +trap cleanup EXIT + +if [ -z "${SCOPE3_API_KEY:-}" ]; then + echo -e "${RED}Error: SCOPE3_API_KEY not set${NC}" + echo " export SCOPE3_API_KEY=your_api_key" + exit 1 +fi + +echo "" +echo "==========================================" +echo " BRAND WORKFLOW TEST (SDK v2)" +echo "==========================================" + +# โ”€โ”€ 1. List brands โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "List brands" +RESULT=$($CLI brands list --take 5 2>&1) && { + pass "Listed brands" + info=$(echo "$RESULT" | extract 'data.length') + echo " $info brand(s) returned" +} || { + fail "Could not list brands" + echo "$RESULT" + exit 1 +} + +# โ”€โ”€ 2. Create brand with manifest URL โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Create brand (manifest URL)" +RESULT=$($CLI brands create --manifest-url "https://example.com/brand-manifest.json" 2>&1) && { + CREATED_BRAND_ID=$(echo "$RESULT" | extract 'data.id') + pass "Created brand: $CREATED_BRAND_ID" +} || { + fail "Could not create brand" + echo "$RESULT" + exit 1 +} + +# โ”€โ”€ 3. Get brand โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Get brand by ID" +RESULT=$($CLI brands get "$CREATED_BRAND_ID" 2>&1) && { + pass "Got brand details" +} || { + fail "Could not get brand $CREATED_BRAND_ID" +} + +# โ”€โ”€ 4. Update brand โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Update brand (new manifest URL)" +RESULT=$($CLI brands update "$CREATED_BRAND_ID" --manifest-url "https://example.com/updated-manifest.json" 2>&1) && { + pass "Updated brand" +} || { + fail "Could not update brand" +} + +# โ”€โ”€ 5. Create brand with inline JSON โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Create brand (inline manifest JSON)" +MANIFEST='{"name":"Test Brand","description":"Automated test brand","industry":"Technology"}' +RESULT=$($CLI brands create --manifest-json "$MANIFEST" 2>&1) && { + INLINE_BRAND_ID=$(echo "$RESULT" | extract 'data.id') + pass "Created brand with inline JSON: $INLINE_BRAND_ID" + # Clean up inline brand + $CLI brands delete "$INLINE_BRAND_ID" > /dev/null 2>&1 && \ + pass "Cleaned up inline brand" || true +} || { + warn "Could not create brand with inline JSON" +} + +# โ”€โ”€ Summary โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +echo "" +echo "==========================================" +echo " BRAND WORKFLOW SUMMARY" +echo "==========================================" +echo "" +echo " Brand: ${CREATED_BRAND_ID:-none}" +echo "" +echo -e "${GREEN}Brand workflow test complete.${NC}" diff --git a/scripts/test-buyer-workflow.sh b/scripts/test-buyer-workflow.sh new file mode 100755 index 0000000..e197c9b --- /dev/null +++ b/scripts/test-buyer-workflow.sh @@ -0,0 +1,202 @@ +#!/bin/bash + +# Scope3 SDK v2 - Buyer Workflow Test +# Tests the full buyer persona flow: advertisers, bundles, products, campaigns +# +# Usage: +# export SCOPE3_API_KEY=your_buyer_api_key +# ./scripts/test-buyer-workflow.sh +# ./scripts/test-buyer-workflow.sh --staging # test against staging + +set -euo pipefail + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +CLI="node dist/cli/index.js --persona buyer --format json" +CREATED_ADVERTISER_ID="" +CREATED_BUNDLE_ID="" +CREATED_CAMPAIGN_ID="" +STEP=0 + +# Use staging if --staging flag passed +if [[ "${1:-}" == "--staging" ]]; then + CLI="$CLI --environment staging" + echo -e "${YELLOW}Using STAGING environment${NC}" +fi + +step() { STEP=$((STEP + 1)); echo -e "\n${BLUE}[$STEP]${NC} $1"; } +pass() { echo -e " ${GREEN}PASS${NC} $1"; } +fail() { echo -e " ${RED}FAIL${NC} $1"; } +warn() { echo -e " ${YELLOW}SKIP${NC} $1"; } +info() { echo -e " $1"; } +extract() { node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(eval('d.$1'));" 2>/dev/null; } + +cleanup() { + echo -e "\n${BLUE}Cleanup${NC}" + if [ -n "$CREATED_CAMPAIGN_ID" ]; then + echo -e " Campaign: $CREATED_CAMPAIGN_ID (delete manually if needed)" + fi + if [ -n "$CREATED_ADVERTISER_ID" ]; then + $CLI -- advertisers delete "$CREATED_ADVERTISER_ID" > /dev/null 2>&1 && \ + pass "Deleted advertiser $CREATED_ADVERTISER_ID" || \ + warn "Could not delete advertiser $CREATED_ADVERTISER_ID" + fi +} +trap cleanup EXIT + +# โ”€โ”€ Checks โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +if [ -z "${SCOPE3_API_KEY:-}" ]; then + echo -e "${RED}Error: SCOPE3_API_KEY not set${NC}" + echo " export SCOPE3_API_KEY=your_api_key" + exit 1 +fi + +echo "" +echo "==========================================" +echo " BUYER WORKFLOW TEST (SDK v2)" +echo "==========================================" + +# โ”€โ”€ 1. List advertisers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "List advertisers" +RESULT=$($CLI advertisers list --take 5 2>&1) && { + pass "Listed advertisers" + info "$(echo "$RESULT" | extract 'data.length') advertiser(s) returned" +} || { + fail "Could not list advertisers" + echo "$RESULT" + exit 1 +} + +# โ”€โ”€ 2. Create advertiser โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Create advertiser" +RESULT=$($CLI advertisers create --name "SDK Test $(date +%s)" --description "Automated test" 2>&1) && { + CREATED_ADVERTISER_ID=$(echo "$RESULT" | extract 'data.id') + pass "Created advertiser: $CREATED_ADVERTISER_ID" +} || { + fail "Could not create advertiser" + echo "$RESULT" + exit 1 +} + +# โ”€โ”€ 3. Get advertiser โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Get advertiser by ID" +RESULT=$($CLI advertisers get "$CREATED_ADVERTISER_ID" 2>&1) && { + NAME=$(echo "$RESULT" | extract 'data.name') + pass "Got advertiser: $NAME" +} || { + fail "Could not get advertiser $CREATED_ADVERTISER_ID" +} + +# โ”€โ”€ 4. Update advertiser โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Update advertiser" +RESULT=$($CLI advertisers update "$CREATED_ADVERTISER_ID" --name "SDK Test Updated" 2>&1) && { + pass "Updated advertiser name" +} || { + fail "Could not update advertiser" +} + +# โ”€โ”€ 5. List buyer brands โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "List buyer brands" +RESULT=$($CLI brands list --take 3 2>&1) && { + pass "Listed buyer brands" +} || { + warn "Could not list brands (may need brand data)" +} + +# โ”€โ”€ 6. Create bundle โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Create bundle for product discovery" +RESULT=$($CLI bundles create \ + --advertiser-id "$CREATED_ADVERTISER_ID" \ + --channels display,video \ + --countries US 2>&1) && { + CREATED_BUNDLE_ID=$(echo "$RESULT" | extract 'data.bundleId') + pass "Created bundle: $CREATED_BUNDLE_ID" +} || { + fail "Could not create bundle" + echo "$RESULT" +} + +# โ”€โ”€ 7. Discover products โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +if [ -n "$CREATED_BUNDLE_ID" ]; then + step "Discover products in bundle" + RESULT=$($CLI bundles discover-products "$CREATED_BUNDLE_ID" --group-limit 3 2>&1) && { + pass "Discovered products" + info "$(echo "$RESULT" | extract 'data.groups?.length || 0') group(s) found" + } || { + warn "No products discovered (normal for test advertisers)" + } +else + step "Discover products in bundle" + warn "Skipped (no bundle created)" +fi + +# โ”€โ”€ 8. Browse products without bundle โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Browse products (no bundle required)" +RESULT=$($CLI bundles browse-products \ + --advertiser-id "$CREATED_ADVERTISER_ID" \ + --channels display 2>&1) && { + pass "Browsed products" +} || { + warn "Could not browse products" +} + +# โ”€โ”€ 9. List campaigns โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "List campaigns" +RESULT=$($CLI campaigns list --take 5 2>&1) && { + pass "Listed campaigns" + info "$(echo "$RESULT" | extract 'data.length') campaign(s) returned" +} || { + fail "Could not list campaigns" +} + +# โ”€โ”€ 10. Create bundle campaign โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +if [ -n "$CREATED_BUNDLE_ID" ]; then + step "Create bundle campaign" + RESULT=$($CLI campaigns create-bundle \ + --advertiser-id "$CREATED_ADVERTISER_ID" \ + --name "SDK Test Campaign $(date +%s)" \ + --bundle-id "$CREATED_BUNDLE_ID" \ + --start-date "2025-06-01" \ + --end-date "2025-06-30" \ + --budget 10000 \ + --channels display,video 2>&1) && { + CREATED_CAMPAIGN_ID=$(echo "$RESULT" | extract 'data.id') + pass "Created bundle campaign: $CREATED_CAMPAIGN_ID" + } || { + warn "Could not create campaign (may need products in bundle)" + echo "$RESULT" | head -3 + } +else + step "Create bundle campaign" + warn "Skipped (no bundle created)" +fi + +# โ”€โ”€ 11. Get campaign โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +if [ -n "$CREATED_CAMPAIGN_ID" ]; then + step "Get campaign by ID" + RESULT=$($CLI campaigns get "$CREATED_CAMPAIGN_ID" 2>&1) && { + pass "Got campaign details" + } || { + warn "Could not get campaign" + } +else + step "Get campaign by ID" + warn "Skipped (no campaign created)" +fi + +# โ”€โ”€ Summary โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +echo "" +echo "==========================================" +echo " BUYER WORKFLOW SUMMARY" +echo "==========================================" +echo "" +echo " Advertiser: ${CREATED_ADVERTISER_ID:-none}" +echo " Bundle: ${CREATED_BUNDLE_ID:-none}" +echo " Campaign: ${CREATED_CAMPAIGN_ID:-none}" +echo "" +echo -e "${GREEN}Buyer workflow test complete.${NC}" diff --git a/scripts/test-partner-workflow.sh b/scripts/test-partner-workflow.sh new file mode 100755 index 0000000..26b61a4 --- /dev/null +++ b/scripts/test-partner-workflow.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +# Scope3 SDK v2 - Partner Workflow Test +# Tests the partner persona flow: health check +# +# Usage: +# export SCOPE3_API_KEY=your_partner_api_key +# ./scripts/test-partner-workflow.sh +# ./scripts/test-partner-workflow.sh --staging + +set -euo pipefail + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Partner CLI doesn't have many commands yet โ€” health is the main one +# We also test the config and skill.md fetching +CLI="node dist/cli/index.js --persona partner --format json" +STEP=0 + +if [[ "${1:-}" == "--staging" ]]; then + CLI="$CLI --environment staging" + echo -e "${YELLOW}Using STAGING environment${NC}" +fi + +step() { STEP=$((STEP + 1)); echo -e "\n${BLUE}[$STEP]${NC} $1"; } +pass() { echo -e " ${GREEN}PASS${NC} $1"; } +fail() { echo -e " ${RED}FAIL${NC} $1"; } +warn() { echo -e " ${YELLOW}SKIP${NC} $1"; } + +if [ -z "${SCOPE3_API_KEY:-}" ]; then + echo -e "${RED}Error: SCOPE3_API_KEY not set${NC}" + echo " export SCOPE3_API_KEY=your_api_key" + exit 1 +fi + +echo "" +echo "==========================================" +echo " PARTNER WORKFLOW TEST (SDK v2)" +echo "==========================================" + +# โ”€โ”€ 1. CLI version โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "CLI version check" +RESULT=$(node dist/cli/index.js --cli-version 2>&1) && { + pass "CLI version: $RESULT" +} || { + fail "Could not get CLI version" +} + +# โ”€โ”€ 2. Config commands โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Config set/get" +node dist/cli/index.js config set persona partner > /dev/null 2>&1 && { + pass "Config set persona=partner" +} || { + warn "Config set failed" +} + +RESULT=$(node dist/cli/index.js config get persona 2>&1) && { + pass "Config get persona: $RESULT" +} || { + warn "Config get failed" +} + +# โ”€โ”€ 3. Fetch skill.md โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +step "Fetch partner skill.md from live API" +RESULT=$(node -e " +const { fetchSkillMd } = require('./dist/skill'); +fetchSkillMd({ persona: 'partner' }).then(s => { + console.log('Lines: ' + s.split('\n').length); + console.log('OK'); +}).catch(e => { console.error(e.message); process.exit(1); }); +" 2>&1) && { + pass "Fetched partner skill.md ($RESULT)" +} || { + warn "Could not fetch skill.md (using bundled fallback)" +} + +# โ”€โ”€ Summary โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +echo "" +echo "==========================================" +echo " PARTNER WORKFLOW SUMMARY" +echo "==========================================" +echo "" +echo " The partner persona currently supports:" +echo " - Health check" +echo " - Config management" +echo " - skill.md fetching" +echo "" +echo " More features coming soon." +echo "" +echo -e "${GREEN}Partner workflow test complete.${NC}" diff --git a/scripts/test-sdk-workflow.ts b/scripts/test-sdk-workflow.ts new file mode 100644 index 0000000..163128f --- /dev/null +++ b/scripts/test-sdk-workflow.ts @@ -0,0 +1,317 @@ +#!/usr/bin/env npx ts-node + +/** + * Scope3 SDK v2 - TypeScript SDK Workflow Test + * + * Tests the SDK programmatically (not via CLI). + * Exercises all 3 personas and core operations. + * + * Usage: + * export SCOPE3_API_KEY=your_api_key + * npx ts-node scripts/test-sdk-workflow.ts + * npx ts-node scripts/test-sdk-workflow.ts --staging + */ + +import { Scope3Client } from '../src'; +import type { Persona, Environment } from '../src/types'; + +const API_KEY = process.env.SCOPE3_API_KEY; +if (!API_KEY) { + console.error('Error: SCOPE3_API_KEY not set'); + process.exit(1); +} + +const isStaging = process.argv.includes('--staging'); +const environment: Environment = isStaging ? 'staging' : 'production'; + +let step = 0; +const log = (msg: string) => { + step++; + console.log(`\n[${step}] ${msg}`); +}; +const pass = (msg: string) => console.log(` PASS ${msg}`); +const fail = (msg: string) => console.log(` FAIL ${msg}`); +const warn = (msg: string) => console.log(` SKIP ${msg}`); + +function makeClient(persona: Persona): Scope3Client { + return new Scope3Client({ + apiKey: API_KEY!, + persona, + environment, + }); +} + +async function testBuyer() { + console.log('\n=========================================='); + console.log(' BUYER PERSONA'); + console.log('=========================================='); + + const client = makeClient('buyer'); + let advertiserId = ''; + let bundleId = ''; + + // List advertisers + log('List advertisers'); + try { + const result = await client.advertisers.list({ take: 3 }); + pass(`${result.data.length} advertiser(s)`); + } catch (e: unknown) { + fail((e as Error).message); + } + + // Create advertiser + log('Create advertiser'); + try { + const result = await client.advertisers.create({ + name: `SDK Test ${Date.now()}`, + description: 'TypeScript SDK test', + }); + advertiserId = result.data.id; + pass(`Created: ${advertiserId}`); + } catch (e: unknown) { + fail((e as Error).message); + } + + // Get advertiser + if (advertiserId) { + log('Get advertiser'); + try { + const result = await client.advertisers.get(advertiserId); + pass(`Name: ${result.data.name}`); + } catch (e: unknown) { + fail((e as Error).message); + } + } + + // Update advertiser + if (advertiserId) { + log('Update advertiser'); + try { + await client.advertisers.update(advertiserId, { name: 'SDK Test Updated' }); + pass('Updated'); + } catch (e: unknown) { + fail((e as Error).message); + } + } + + // List buyer brands + log('List buyer brands'); + try { + const result = await client.buyerBrands.list({ take: 3 }); + pass(`${result.data.length} brand(s)`); + } catch (e: unknown) { + warn((e as Error).message); + } + + // Create bundle + if (advertiserId) { + log('Create bundle'); + try { + const result = await client.bundles.create({ + advertiserId, + channels: ['display', 'video'], + countries: ['US'], + }); + bundleId = result.data.bundleId; + pass(`Created: ${bundleId}`); + } catch (e: unknown) { + fail((e as Error).message); + } + } + + // Discover products + if (bundleId) { + log('Discover products'); + try { + const result = await client.bundles.discoverProducts(bundleId, { groupLimit: 3 }); + pass(`${result.data.groups?.length ?? 0} group(s)`); + } catch (e: unknown) { + warn((e as Error).message); + } + } + + // List campaigns + log('List campaigns'); + try { + const result = await client.campaigns.list({ take: 3 }); + pass(`${result.data.length} campaign(s)`); + } catch (e: unknown) { + fail((e as Error).message); + } + + // Get skill.md + log('Get buyer skill.md'); + try { + const skill = await client.getSkill(); + pass(`${skill.name} v${skill.version} - ${skill.commands.length} commands`); + } catch (e: unknown) { + warn((e as Error).message); + } + + // Cleanup + if (advertiserId) { + log('Delete test advertiser'); + try { + await client.advertisers.delete(advertiserId); + pass(`Deleted: ${advertiserId}`); + } catch (e: unknown) { + warn((e as Error).message); + } + } +} + +async function testBrand() { + console.log('\n=========================================='); + console.log(' BRAND PERSONA'); + console.log('=========================================='); + + const client = makeClient('brand'); + let brandId = ''; + + // List brands + log('List brands'); + try { + const result = await client.brands.list({ take: 3 }); + pass(`${result.data.length} brand(s)`); + } catch (e: unknown) { + fail((e as Error).message); + } + + // Create brand + log('Create brand'); + try { + const result = await client.brands.create({ + manifestUrl: 'https://example.com/test-manifest.json', + }); + brandId = result.data.id; + pass(`Created: ${brandId}`); + } catch (e: unknown) { + fail((e as Error).message); + } + + // Get brand + if (brandId) { + log('Get brand'); + try { + const result = await client.brands.get(brandId); + pass(`Got brand: ${result.data.id}`); + } catch (e: unknown) { + fail((e as Error).message); + } + } + + // Update brand + if (brandId) { + log('Update brand'); + try { + await client.brands.update(brandId, { + manifestUrl: 'https://example.com/updated-manifest.json', + }); + pass('Updated'); + } catch (e: unknown) { + fail((e as Error).message); + } + } + + // Get skill.md + log('Get brand skill.md'); + try { + const skill = await client.getSkill(); + pass(`${skill.name} v${skill.version} - ${skill.commands.length} commands`); + } catch (e: unknown) { + warn((e as Error).message); + } + + // Cleanup + if (brandId) { + log('Delete test brand'); + try { + await client.brands.delete(brandId); + pass(`Deleted: ${brandId}`); + } catch (e: unknown) { + warn((e as Error).message); + } + } +} + +async function testPartner() { + console.log('\n=========================================='); + console.log(' PARTNER PERSONA'); + console.log('=========================================='); + + const client = makeClient('partner'); + + // Health check + log('Health check'); + try { + const result = await client.health.check(); + pass(`Status: ${result.data.status}`); + } catch (e: unknown) { + fail((e as Error).message); + } + + // Get skill.md + log('Get partner skill.md'); + try { + const skill = await client.getSkill(); + pass(`${skill.name} v${skill.version} - ${skill.commands.length} commands`); + } catch (e: unknown) { + warn((e as Error).message); + } +} + +async function testPersonaGuards() { + console.log('\n=========================================='); + console.log(' PERSONA GUARDS'); + console.log('=========================================='); + + // Verify wrong-persona access throws + const buyer = makeClient('buyer'); + + log('Buyer cannot access brands (brand persona)'); + try { + buyer.brands; // eslint-disable-line @typescript-eslint/no-unused-expressions + fail('Should have thrown'); + } catch (e: unknown) { + pass(`Threw: ${(e as Error).message}`); + } + + log('Buyer cannot access health (partner persona)'); + try { + buyer.health; // eslint-disable-line @typescript-eslint/no-unused-expressions + fail('Should have thrown'); + } catch (e: unknown) { + pass(`Threw: ${(e as Error).message}`); + } + + const brand = makeClient('brand'); + + log('Brand cannot access advertisers (buyer persona)'); + try { + brand.advertisers; // eslint-disable-line @typescript-eslint/no-unused-expressions + fail('Should have thrown'); + } catch (e: unknown) { + pass(`Threw: ${(e as Error).message}`); + } +} + +async function main() { + console.log('=========================================='); + console.log(' SCOPE3 SDK v2 WORKFLOW TEST'); + console.log(` Environment: ${environment}`); + console.log('=========================================='); + + await testBuyer(); + await testBrand(); + await testPartner(); + await testPersonaGuards(); + + console.log('\n=========================================='); + console.log(' ALL DONE'); + console.log('==========================================\n'); +} + +main().catch((e) => { + console.error('Fatal error:', e); + process.exit(1); +}); diff --git a/scripts/update-schemas.sh b/scripts/update-schemas.sh deleted file mode 100755 index 89ad499..0000000 --- a/scripts/update-schemas.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -set -e - -# Base URL for the OpenAPI specs -BASE_URL="https://raw.githubusercontent.com/scope3data/agentic-api/main/mintlify" - -# Set up curl with authentication if GITHUB_TOKEN is available -if [ -n "$GITHUB_TOKEN" ]; then - AUTH_HEADER=(-H "Authorization: token $GITHUB_TOKEN") -else - AUTH_HEADER=() -fi - -echo "Downloading OpenAPI schemas..." - -# Download outcome-agent-openapi.yaml -echo "Fetching outcome-agent-openapi.yaml..." -curl -f "${AUTH_HEADER[@]}" -o outcome-agent-openapi.yaml "$BASE_URL/outcome-agent-openapi.yaml" - -# Download partner-api.yaml -echo "Fetching partner-api.yaml..." -curl -f "${AUTH_HEADER[@]}" -o partner-api.yaml "$BASE_URL/partner-api.yaml" - -# Download platform-api.yaml -echo "Fetching platform-api.yaml..." -curl -f "${AUTH_HEADER[@]}" -o platform-api.yaml "$BASE_URL/platform-api.yaml" - -echo "Generating TypeScript types and SDK..." - -# Generate types -npm run generate-outcome-agent-types -npm run generate-partner-api-types -npm run generate-platform-api-types - -# Generate SDK from types -npm run generate-sdk - -echo "โœ… Schemas updated, types generated, and SDK regenerated successfully!" diff --git a/src/__tests__/adapters/base.test.ts b/src/__tests__/adapters/base.test.ts new file mode 100644 index 0000000..ba019ab --- /dev/null +++ b/src/__tests__/adapters/base.test.ts @@ -0,0 +1,119 @@ +/** + * Tests for base adapter utilities + */ + +import { + Scope3ApiError, + getDefaultBaseUrl, + resolveBaseUrl, + resolveVersion, + resolvePersona, +} from '../../adapters/base'; + +describe('Scope3ApiError', () => { + it('should create error with status and message', () => { + const error = new Scope3ApiError(404, 'Not found'); + expect(error.status).toBe(404); + expect(error.message).toBe('Not found'); + expect(error.name).toBe('Scope3ApiError'); + expect(error.details).toBeUndefined(); + }); + + it('should create error with details', () => { + const details = { field: 'name', reason: 'required' }; + const error = new Scope3ApiError(400, 'Validation error', details); + expect(error.status).toBe(400); + expect(error.message).toBe('Validation error'); + expect(error.details).toEqual(details); + }); + + it('should be an instance of Error', () => { + const error = new Scope3ApiError(500, 'Internal error'); + expect(error).toBeInstanceOf(Error); + expect(error).toBeInstanceOf(Scope3ApiError); + }); + + it('should have a stack trace', () => { + const error = new Scope3ApiError(500, 'Internal error'); + expect(error.stack).toBeDefined(); + }); +}); + +describe('getDefaultBaseUrl', () => { + it('should return production URL by default', () => { + expect(getDefaultBaseUrl()).toBe('https://api.agentic.scope3.com'); + }); + + it('should return production URL when specified', () => { + expect(getDefaultBaseUrl('production')).toBe('https://api.agentic.scope3.com'); + }); + + it('should return staging URL', () => { + expect(getDefaultBaseUrl('staging')).toBe('https://api.agentic.staging.scope3.com'); + }); +}); + +describe('resolveBaseUrl', () => { + it('should use custom base URL when provided', () => { + expect(resolveBaseUrl({ apiKey: 'k', persona: 'buyer', baseUrl: 'https://custom.com' })).toBe( + 'https://custom.com' + ); + }); + + it('should strip trailing slash from custom URL', () => { + expect(resolveBaseUrl({ apiKey: 'k', persona: 'buyer', baseUrl: 'https://custom.com/' })).toBe( + 'https://custom.com' + ); + }); + + it('should use production URL by default', () => { + expect(resolveBaseUrl({ apiKey: 'k', persona: 'buyer' })).toBe( + 'https://api.agentic.scope3.com' + ); + }); + + it('should use staging URL when environment is staging', () => { + expect(resolveBaseUrl({ apiKey: 'k', persona: 'buyer', environment: 'staging' })).toBe( + 'https://api.agentic.staging.scope3.com' + ); + }); + + it('should prefer custom baseUrl over environment', () => { + expect( + resolveBaseUrl({ + apiKey: 'k', + persona: 'buyer', + baseUrl: 'https://custom.com', + environment: 'staging', + }) + ).toBe('https://custom.com'); + }); +}); + +describe('resolveVersion', () => { + it('should default to v2', () => { + expect(resolveVersion({ apiKey: 'k', persona: 'buyer' })).toBe('v2'); + }); + + it('should use v1 when specified', () => { + expect(resolveVersion({ apiKey: 'k', persona: 'buyer', version: 'v1' })).toBe('v1'); + }); + + it('should use latest when specified', () => { + expect(resolveVersion({ apiKey: 'k', persona: 'buyer', version: 'latest' })).toBe('latest'); + }); +}); + +describe('resolvePersona', () => { + it('should return buyer', () => { + expect(resolvePersona({ apiKey: 'k', persona: 'buyer' })).toBe('buyer'); + }); + + it('should return brand', () => { + expect(resolvePersona({ apiKey: 'k', persona: 'brand' })).toBe('brand'); + }); + + it('should return partner', () => { + expect(resolvePersona({ apiKey: 'k', persona: 'partner' })).toBe('partner'); + }); +}); diff --git a/src/__tests__/adapters/mcp.test.ts b/src/__tests__/adapters/mcp.test.ts new file mode 100644 index 0000000..10e71e9 --- /dev/null +++ b/src/__tests__/adapters/mcp.test.ts @@ -0,0 +1,311 @@ +/** + * Tests for MCP adapter + */ + +import { McpAdapter } from '../../adapters/mcp'; +import { Scope3ApiError } from '../../adapters/base'; + +// Mock @modelcontextprotocol/sdk +const mockConnect = jest.fn(); +const mockClose = jest.fn(); +const mockCallTool = jest.fn(); + +jest.mock('@modelcontextprotocol/sdk/client/index.js', () => ({ + Client: jest.fn().mockImplementation(() => ({ + connect: mockConnect, + close: mockClose, + callTool: mockCallTool, + })), +})); + +jest.mock('@modelcontextprotocol/sdk/client/streamableHttp.js', () => ({ + StreamableHTTPClientTransport: jest.fn().mockImplementation(() => ({ + close: jest.fn(), + })), +})); + +describe('McpAdapter', () => { + beforeEach(() => { + mockConnect.mockReset(); + mockClose.mockReset(); + mockCallTool.mockReset(); + }); + + describe('initialization', () => { + it('should initialize with default values', () => { + const adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer' }); + expect(adapter.baseUrl).toBe('https://api.agentic.scope3.com'); + expect(adapter.version).toBe('v2'); + expect(adapter.persona).toBe('buyer'); + expect(adapter.debug).toBe(false); + }); + + it('should use staging URL', () => { + const adapter = new McpAdapter({ + apiKey: 'test-key', + persona: 'buyer', + environment: 'staging', + }); + expect(adapter.baseUrl).toBe('https://api.agentic.staging.scope3.com'); + }); + + it('should use custom base URL', () => { + const adapter = new McpAdapter({ + apiKey: 'test-key', + persona: 'buyer', + baseUrl: 'https://custom.com', + }); + expect(adapter.baseUrl).toBe('https://custom.com'); + }); + + it('should enable debug mode', () => { + const adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer', debug: true }); + expect(adapter.debug).toBe(true); + }); + }); + + describe('connect', () => { + it('should connect to MCP server', async () => { + const adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.connect(); + expect(mockConnect).toHaveBeenCalledTimes(1); + }); + + it('should not reconnect if already connected', async () => { + const adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.connect(); + await adapter.connect(); + expect(mockConnect).toHaveBeenCalledTimes(1); + }); + + it('should throw Scope3ApiError on connection failure', async () => { + mockConnect.mockRejectedValue(new Error('Connection refused')); + const adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await expect(adapter.connect()).rejects.toThrow(Scope3ApiError); + await expect(adapter.connect()).rejects.toMatchObject({ + status: 0, + }); + }); + }); + + describe('disconnect', () => { + it('should disconnect from MCP server', async () => { + const adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.connect(); + await adapter.disconnect(); + expect(mockClose).toHaveBeenCalledTimes(1); + }); + + it('should be no-op if not connected', async () => { + const adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.disconnect(); + expect(mockClose).not.toHaveBeenCalled(); + }); + }); + + describe('request - api_call tool', () => { + let adapter: McpAdapter; + + beforeEach(async () => { + adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer' }); + mockCallTool.mockResolvedValue({ + structuredContent: { id: '123' }, + }); + }); + + it('should call api_call tool for GET /advertisers', async () => { + await adapter.request('GET', '/advertisers'); + expect(mockCallTool).toHaveBeenCalledWith({ + name: 'api_call', + arguments: { + method: 'GET', + path: '/api/v2/buyer/advertisers', + }, + }); + }); + + it('should call api_call tool for POST /advertisers with body', async () => { + await adapter.request('POST', '/advertisers', { name: 'Test' }); + expect(mockCallTool).toHaveBeenCalledWith({ + name: 'api_call', + arguments: { + method: 'POST', + path: '/api/v2/buyer/advertisers', + body: { name: 'Test' }, + }, + }); + }); + + it('should call api_call tool for GET /advertisers/123', async () => { + await adapter.request('GET', '/advertisers/123'); + expect(mockCallTool).toHaveBeenCalledWith({ + name: 'api_call', + arguments: { + method: 'GET', + path: '/api/v2/buyer/advertisers/123', + }, + }); + }); + + it('should append query params to path', async () => { + await adapter.request('GET', '/campaigns', undefined, { + params: { take: 10, status: 'ACTIVE' }, + }); + expect(mockCallTool).toHaveBeenCalledWith({ + name: 'api_call', + arguments: { + method: 'GET', + path: expect.stringContaining('/api/v2/buyer/campaigns?'), + }, + }); + const callArgs = mockCallTool.mock.calls[0][0]; + expect(callArgs.arguments.path).toContain('take=10'); + expect(callArgs.arguments.path).toContain('status=ACTIVE'); + }); + + it('should skip undefined query params', async () => { + await adapter.request('GET', '/campaigns', undefined, { + params: { take: 10, status: undefined }, + }); + const callArgs = mockCallTool.mock.calls[0][0]; + expect(callArgs.arguments.path).toContain('take=10'); + expect(callArgs.arguments.path).not.toContain('status'); + }); + + it('should not include body for GET requests', async () => { + await adapter.request('GET', '/advertisers'); + const callArgs = mockCallTool.mock.calls[0][0]; + expect(callArgs.arguments.body).toBeUndefined(); + }); + + it('should include body for PUT requests', async () => { + await adapter.request('PUT', '/advertisers/123', { name: 'Updated' }); + expect(mockCallTool).toHaveBeenCalledWith({ + name: 'api_call', + arguments: { + method: 'PUT', + path: '/api/v2/buyer/advertisers/123', + body: { name: 'Updated' }, + }, + }); + }); + + it('should include body for DELETE requests', async () => { + await adapter.request('DELETE', '/bundles/123/products', { productIds: ['p1'] }); + expect(mockCallTool).toHaveBeenCalledWith({ + name: 'api_call', + arguments: { + method: 'DELETE', + path: '/api/v2/buyer/bundles/123/products', + body: { productIds: ['p1'] }, + }, + }); + }); + + it('should use brand persona in path', async () => { + const brandAdapter = new McpAdapter({ apiKey: 'test-key', persona: 'brand' }); + mockCallTool.mockResolvedValue({ structuredContent: {} }); + await brandAdapter.request('GET', '/brands'); + expect(mockCallTool).toHaveBeenCalledWith({ + name: 'api_call', + arguments: { + method: 'GET', + path: '/api/v2/brand/brands', + }, + }); + }); + + it('should map latest version to v2 in path', async () => { + const latestAdapter = new McpAdapter({ + apiKey: 'test-key', + persona: 'buyer', + version: 'latest', + }); + mockCallTool.mockResolvedValue({ structuredContent: {} }); + await latestAdapter.request('GET', '/advertisers'); + expect(mockCallTool).toHaveBeenCalledWith({ + name: 'api_call', + arguments: { + method: 'GET', + path: '/api/v2/buyer/advertisers', + }, + }); + }); + }); + + describe('request - response handling', () => { + let adapter: McpAdapter; + + beforeEach(() => { + adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer' }); + }); + + it('should return structuredContent when available', async () => { + mockCallTool.mockResolvedValue({ + structuredContent: { id: '123', name: 'Test' }, + }); + + const result = await adapter.request('GET', '/advertisers/123'); + expect(result).toEqual({ id: '123', name: 'Test' }); + }); + + it('should parse text content as JSON', async () => { + mockCallTool.mockResolvedValue({ + content: [{ type: 'text', text: '{"id":"123"}' }], + }); + + const result = await adapter.request('GET', '/advertisers/123'); + expect(result).toEqual({ id: '123' }); + }); + + it('should return text content as message when not JSON', async () => { + mockCallTool.mockResolvedValue({ + content: [{ type: 'text', text: 'Campaign executed successfully' }], + }); + + const result = await adapter.request<{ message: string }>('POST', '/campaigns/123/execute'); + expect(result).toEqual({ message: 'Campaign executed successfully' }); + }); + + it('should throw when no content returned', async () => { + mockCallTool.mockResolvedValue({}); + + await expect(adapter.request('GET', '/advertisers/123')).rejects.toThrow(Scope3ApiError); + await expect(adapter.request('GET', '/advertisers/123')).rejects.toMatchObject({ + status: 500, + message: 'MCP returned no content', + }); + }); + + it('should wrap non-Scope3ApiError errors', async () => { + mockCallTool.mockRejectedValue(new Error('MCP timeout')); + + await expect(adapter.request('GET', '/advertisers')).rejects.toThrow(Scope3ApiError); + await expect(adapter.request('GET', '/advertisers')).rejects.toMatchObject({ + status: 500, + message: expect.stringContaining('MCP timeout'), + }); + }); + + it('should re-throw Scope3ApiError as-is', async () => { + mockCallTool.mockRejectedValue(new Scope3ApiError(404, 'Not found')); + + await expect(adapter.request('GET', '/advertisers/999')).rejects.toMatchObject({ + status: 404, + message: 'Not found', + }); + }); + }); + + describe('request - auto connect', () => { + it('should auto-connect on first request', async () => { + const adapter = new McpAdapter({ apiKey: 'test-key', persona: 'buyer' }); + mockCallTool.mockResolvedValue({ + structuredContent: { items: [] }, + }); + + await adapter.request('GET', '/advertisers'); + expect(mockConnect).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/src/__tests__/adapters/rest.test.ts b/src/__tests__/adapters/rest.test.ts new file mode 100644 index 0000000..21112e1 --- /dev/null +++ b/src/__tests__/adapters/rest.test.ts @@ -0,0 +1,268 @@ +/** + * Tests for REST adapter + */ + +import { RestAdapter } from '../../adapters/rest'; +import { Scope3ApiError } from '../../adapters/base'; + +// Mock fetch +const mockFetch = jest.fn(); +global.fetch = mockFetch; + +describe('RestAdapter', () => { + beforeEach(() => { + mockFetch.mockReset(); + }); + + describe('initialization', () => { + it('should initialize with default values', () => { + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + expect(adapter.baseUrl).toBe('https://api.agentic.scope3.com'); + expect(adapter.version).toBe('v2'); + expect(adapter.persona).toBe('buyer'); + expect(adapter.debug).toBe(false); + }); + + it('should use staging URL', () => { + const adapter = new RestAdapter({ + apiKey: 'test-key', + persona: 'buyer', + environment: 'staging', + }); + expect(adapter.baseUrl).toBe('https://api.agentic.staging.scope3.com'); + }); + + it('should use custom base URL', () => { + const adapter = new RestAdapter({ + apiKey: 'test-key', + persona: 'buyer', + baseUrl: 'https://custom.com', + }); + expect(adapter.baseUrl).toBe('https://custom.com'); + }); + }); + + describe('request', () => { + it('should make GET request with correct URL including persona', async () => { + mockFetch.mockResolvedValue({ + ok: true, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({ id: '123' }), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.request('GET', '/advertisers/123'); + + expect(mockFetch).toHaveBeenCalledWith( + 'https://api.agentic.scope3.com/api/v2/buyer/advertisers/123', + expect.objectContaining({ + method: 'GET', + headers: expect.objectContaining({ + Authorization: 'Bearer test-key', + }), + }) + ); + }); + + it('should make POST request with body', async () => { + mockFetch.mockResolvedValue({ + ok: true, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({ id: '123', name: 'Test' }), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.request('POST', '/advertisers', { name: 'Test' }); + + expect(mockFetch).toHaveBeenCalledWith( + 'https://api.agentic.scope3.com/api/v2/buyer/advertisers', + expect.objectContaining({ + method: 'POST', + body: JSON.stringify({ name: 'Test' }), + }) + ); + }); + + it('should add query params for GET', async () => { + mockFetch.mockResolvedValue({ + ok: true, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({ items: [] }), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.request('GET', '/advertisers', undefined, { + params: { take: 10, skip: 0, status: 'ACTIVE' }, + }); + + expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('take=10'), expect.anything()); + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('status=ACTIVE'), + expect.anything() + ); + }); + + it('should throw Scope3ApiError on 4xx', async () => { + mockFetch.mockResolvedValue({ + ok: false, + status: 404, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({ message: 'Not found' }), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + + await expect(adapter.request('GET', '/advertisers/999')).rejects.toThrow(Scope3ApiError); + await expect(adapter.request('GET', '/advertisers/999')).rejects.toMatchObject({ + status: 404, + message: 'Not found', + }); + }); + + it('should throw Scope3ApiError on network error', async () => { + mockFetch.mockRejectedValue(new Error('Network error')); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + + await expect(adapter.request('GET', '/advertisers')).rejects.toThrow(Scope3ApiError); + }); + + it('should send body with DELETE requests', async () => { + mockFetch.mockResolvedValue({ + ok: true, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({}), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.request('DELETE', '/bundles/123/products', { + productIds: ['prod-1', 'prod-2'], + }); + + expect(mockFetch).toHaveBeenCalledWith( + expect.any(String), + expect.objectContaining({ + method: 'DELETE', + body: JSON.stringify({ productIds: ['prod-1', 'prod-2'] }), + }) + ); + }); + + it('should send body with PUT requests', async () => { + mockFetch.mockResolvedValue({ + ok: true, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({ id: '123', name: 'Updated' }), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.request('PUT', '/advertisers/123', { name: 'Updated' }); + + expect(mockFetch).toHaveBeenCalledWith( + expect.any(String), + expect.objectContaining({ + method: 'PUT', + body: JSON.stringify({ name: 'Updated' }), + }) + ); + }); + + it('should map "latest" version to v2 in URL', async () => { + mockFetch.mockResolvedValue({ + ok: true, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({}), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer', version: 'latest' }); + await adapter.request('GET', '/advertisers'); + + expect(mockFetch).toHaveBeenCalledWith( + 'https://api.agentic.scope3.com/api/v2/buyer/advertisers', + expect.anything() + ); + }); + + it('should not send body for GET requests', async () => { + mockFetch.mockResolvedValue({ + ok: true, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({}), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.request('GET', '/advertisers', { ignored: true }); + + const callArgs = mockFetch.mock.calls[0][1]; + expect(callArgs.body).toBeUndefined(); + }); + + it('should handle non-JSON response', async () => { + mockFetch.mockResolvedValue({ + ok: true, + headers: { get: (key: string) => (key === 'content-type' ? 'text/plain' : null) }, + text: () => Promise.resolve('OK'), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + const result = await adapter.request('POST', '/campaigns/123/execute'); + + expect(result).toEqual({ message: 'OK' }); + }); + + it('should handle error response without message field', async () => { + mockFetch.mockResolvedValue({ + ok: false, + status: 500, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({ code: 'INTERNAL_ERROR' }), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + + await expect(adapter.request('GET', '/advertisers')).rejects.toMatchObject({ + status: 500, + message: 'HTTP 500', + }); + }); + + it('should skip undefined query params', async () => { + mockFetch.mockResolvedValue({ + ok: true, + headers: { get: (key: string) => (key === 'content-type' ? 'application/json' : null) }, + json: () => Promise.resolve({ items: [] }), + }); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + await adapter.request('GET', '/advertisers', undefined, { + params: { take: 10, skip: undefined, status: undefined }, + }); + + const url = mockFetch.mock.calls[0][0] as string; + expect(url).toContain('take=10'); + expect(url).not.toContain('skip'); + expect(url).not.toContain('status'); + }); + + it('should throw timeout error on AbortError', async () => { + const abortError = new Error('The operation was aborted'); + abortError.name = 'AbortError'; + mockFetch.mockRejectedValue(abortError); + + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + + await expect(adapter.request('GET', '/advertisers')).rejects.toMatchObject({ + status: 408, + }); + }); + }); + + describe('connect/disconnect', () => { + it('should be no-op for REST adapter', async () => { + const adapter = new RestAdapter({ apiKey: 'test-key', persona: 'buyer' }); + + await expect(adapter.connect()).resolves.toBeUndefined(); + await expect(adapter.disconnect()).resolves.toBeUndefined(); + }); + }); +}); diff --git a/src/__tests__/cli-format.test.ts b/src/__tests__/cli-format.test.ts deleted file mode 100644 index 92aa97f..0000000 --- a/src/__tests__/cli-format.test.ts +++ /dev/null @@ -1,362 +0,0 @@ -/** - * Tests for CLI output formatting (formatOutput function) - * - * Tests all three output formats: - * - JSON: raw JSON output - * - Table: columnar display with cli-table3 - * - List: detailed view with all fields - */ - -import chalk from 'chalk'; - -// We need to test the formatOutput function which is currently in cli.ts -// For better testability, we'll extract it to a separate module in recommendations -// For now, we'll test the behavior by mocking console.log and importing the function - -describe('CLI Output Formatting', () => { - let consoleLogSpy: jest.SpyInstance; - - beforeEach(() => { - consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(); - }); - - afterEach(() => { - consoleLogSpy.mockRestore(); - }); - - // Helper to create formatOutput function (extracted from cli.ts) - function formatOutput(data: unknown, format: string): void { - if (format === 'json') { - console.log(JSON.stringify(data, null, 2)); - return; - } - - if (!data) { - console.log(chalk.yellow('No data to display')); - return; - } - - const dataObj = data as Record; - let actualData: unknown = dataObj.data || data; - - if ( - typeof actualData === 'object' && - actualData && - !Array.isArray(actualData) && - 'items' in actualData && - Array.isArray((actualData as Record).items) - ) { - actualData = (actualData as Record).items; - } - - if ( - typeof actualData === 'object' && - actualData && - !Array.isArray(actualData) && - Object.keys(actualData).length === 1 && - 'message' in actualData - ) { - console.log(String((actualData as Record).message)); - return; - } - - if (Array.isArray(actualData)) { - if (actualData.length === 0) { - console.log(chalk.yellow('No results found')); - return; - } - - if (format === 'list') { - actualData.forEach((item, index) => { - console.log(chalk.cyan(`\n${index + 1}.`)); - Object.entries(item).forEach(([key, value]) => { - let displayValue: string; - if (value === null || value === undefined) { - displayValue = chalk.gray('(empty)'); - } else if (typeof value === 'object') { - displayValue = JSON.stringify(value, null, 2); - } else { - displayValue = String(value); - } - console.log(` ${chalk.yellow(key)}: ${displayValue}`); - }); - }); - console.log(); - } else { - // Table format - simplified for testing - console.log('TABLE FORMAT'); - } - } else if (typeof actualData === 'object' && actualData) { - console.log('SINGLE OBJECT TABLE'); - } else { - console.log(actualData); - } - - if (dataObj.success !== undefined) { - console.log(dataObj.success ? chalk.green('โœ“ Success') : chalk.red('โœ— Failed')); - } - } - - describe('JSON format', () => { - it('should output raw JSON for simple objects', () => { - const data = { id: '123', name: 'Test Campaign' }; - formatOutput(data, 'json'); - - expect(consoleLogSpy).toHaveBeenCalledWith(JSON.stringify(data, null, 2)); - }); - - it('should output raw JSON for arrays', () => { - const data = [{ id: '1' }, { id: '2' }]; - formatOutput(data, 'json'); - - expect(consoleLogSpy).toHaveBeenCalledWith(JSON.stringify(data, null, 2)); - }); - - it('should output raw JSON for nested structures', () => { - const data = { - items: [{ id: '1', nested: { deep: 'value' } }], - metadata: { total: 1 }, - }; - formatOutput(data, 'json'); - - expect(consoleLogSpy).toHaveBeenCalledWith(JSON.stringify(data, null, 2)); - }); - - it('should handle null data', () => { - formatOutput(null, 'json'); - // JSON format outputs "null" as JSON, which is valid - expect(consoleLogSpy).toHaveBeenCalledWith('null'); - }); - - it('should handle undefined data', () => { - formatOutput(undefined, 'json'); - // JSON format outputs undefined directly - expect(consoleLogSpy).toHaveBeenCalled(); - }); - }); - - describe('data unwrapping', () => { - it('should unwrap ToolResponse wrapper (data field)', () => { - const data = { - success: true, - data: { id: '123', name: 'Campaign' }, - }; - formatOutput(data, 'json'); - - const output = JSON.parse(consoleLogSpy.mock.calls[0][0]); - // In JSON format, we get the full structure - expect(output.data).toEqual({ id: '123', name: 'Campaign' }); - }); - - it('should unwrap items array from response', () => { - const data = { - items: [{ id: '1' }, { id: '2' }], - total: 2, - }; - formatOutput(data, 'list'); - - // Should display items - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('1.')); - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('2.')); - }); - - it('should handle nested data wrapper', () => { - const data = { - success: true, - data: { - items: [{ id: '1' }], - }, - }; - formatOutput(data, 'list'); - - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('1.')); - }); - }); - - describe('message-only responses', () => { - it('should display plain message for single message objects', () => { - const data = { message: 'Operation completed successfully' }; - formatOutput(data, 'table'); - - expect(consoleLogSpy).toHaveBeenCalledWith('Operation completed successfully'); - expect(consoleLogSpy).not.toHaveBeenCalledWith(expect.stringContaining('TABLE')); - }); - - it('should display plain message in list format', () => { - const data = { message: 'Resource deleted' }; - formatOutput(data, 'list'); - - expect(consoleLogSpy).toHaveBeenCalledWith('Resource deleted'); - }); - - it('should use table format for message with other fields', () => { - const data = { message: 'Success', id: '123' }; - formatOutput(data, 'table'); - - expect(consoleLogSpy).toHaveBeenCalledWith('SINGLE OBJECT TABLE'); - }); - }); - - describe('list format', () => { - it('should display numbered list with all fields', () => { - const data = [ - { id: '1', name: 'Item 1', status: 'active' }, - { id: '2', name: 'Item 2', status: 'inactive' }, - ]; - formatOutput(data, 'list'); - - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('1.')); - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('2.')); - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringMatching(/id.*1/)); - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringMatching(/name.*Item 1/)); - }); - - it('should show empty values as (empty)', () => { - const data = [{ id: '1', name: null, description: undefined }]; - formatOutput(data, 'list'); - - const emptyCall = consoleLogSpy.mock.calls.find((call) => call[0].includes('(empty)')); - expect(emptyCall).toBeDefined(); - }); - - it('should format nested objects as JSON', () => { - const data = [ - { - id: '1', - metadata: { created: '2024-01-01', tags: ['tag1', 'tag2'] }, - }, - ]; - formatOutput(data, 'list'); - - const jsonCall = consoleLogSpy.mock.calls.find((call) => call[0].includes('"created"')); - expect(jsonCall).toBeDefined(); - }); - - it('should handle empty array', () => { - formatOutput([], 'list'); - - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('No results found')); - }); - - it('should add extra line after list', () => { - const data = [{ id: '1' }]; - formatOutput(data, 'list'); - - // Last call should be empty line - const lastCall = consoleLogSpy.mock.calls[consoleLogSpy.mock.calls.length - 1]; - expect(lastCall[0]).toBe(undefined); - }); - }); - - describe('table format', () => { - it('should use table for arrays (simplified test)', () => { - const data = [{ id: '1', name: 'Item' }]; - formatOutput(data, 'table'); - - expect(consoleLogSpy).toHaveBeenCalledWith('TABLE FORMAT'); - }); - - it('should use table for single objects', () => { - const data = { id: '123', name: 'Campaign', status: 'active' }; - formatOutput(data, 'table'); - - expect(consoleLogSpy).toHaveBeenCalledWith('SINGLE OBJECT TABLE'); - }); - - it('should handle empty array', () => { - formatOutput([], 'table'); - - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('No results found')); - }); - }); - - describe('success indicator', () => { - // Note: Success indicator logic is in the full implementation (cli.ts) - // This simplified test version doesn't implement it to keep tests focused - // Integration tests should cover the full formatOutput behavior - - it('should handle success field in data', () => { - const data = { success: true, data: { id: '123' } }; - formatOutput(data, 'json'); - - expect(consoleLogSpy).toHaveBeenCalled(); - const output = consoleLogSpy.mock.calls[0][0]; - expect(output).toContain('success'); - }); - }); - - describe('edge cases', () => { - it('should handle primitive values', () => { - formatOutput('plain string', 'table'); - expect(consoleLogSpy).toHaveBeenCalledWith('plain string'); - - consoleLogSpy.mockClear(); - formatOutput(42, 'table'); - expect(consoleLogSpy).toHaveBeenCalledWith(42); - - consoleLogSpy.mockClear(); - formatOutput(true, 'table'); - expect(consoleLogSpy).toHaveBeenCalledWith(true); - }); - - it('should handle array of primitives', () => { - formatOutput(['a', 'b', 'c'], 'list'); - // Should handle gracefully (may not have perfect output) - expect(consoleLogSpy).toHaveBeenCalled(); - }); - - it('should handle deeply nested structures', () => { - const data = { - items: [ - { - id: '1', - level1: { - level2: { - level3: { - value: 'deep', - }, - }, - }, - }, - ], - }; - formatOutput(data, 'list'); - - expect(consoleLogSpy).toHaveBeenCalled(); - }); - - it('should handle special characters in values', () => { - const data = [ - { - id: '1', - name: 'Campaign "Special" & ', - emoji: '๐ŸŽ‰ Success!', - }, - ]; - formatOutput(data, 'list'); - - expect(consoleLogSpy).toHaveBeenCalled(); - }); - }); - - describe('format parameter validation', () => { - it('should default to table for unknown format', () => { - const data = [{ id: '1' }]; - formatOutput(data, 'unknown-format'); - - // Should fall back to table - expect(consoleLogSpy).toHaveBeenCalledWith('TABLE FORMAT'); - }); - - it('should be case-sensitive', () => { - const data = { id: '123' }; - - formatOutput(data, 'JSON'); - expect(consoleLogSpy).not.toHaveBeenCalledWith(expect.stringContaining('{')); - - consoleLogSpy.mockClear(); - formatOutput(data, 'json'); - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('{')); - }); - }); -}); diff --git a/src/__tests__/cli/format.test.ts b/src/__tests__/cli/format.test.ts new file mode 100644 index 0000000..9c5cf79 --- /dev/null +++ b/src/__tests__/cli/format.test.ts @@ -0,0 +1,198 @@ +/** + * Tests for CLI format utilities + */ + +import { formatOutput, printError, printSuccess, printWarning } from '../../cli/format'; + +// Capture console output +let consoleOutput: string[]; +let consoleErrors: string[]; + +const originalLog = console.log; +const originalError = console.error; + +beforeEach(() => { + consoleOutput = []; + consoleErrors = []; + console.log = jest.fn((...args: unknown[]) => { + consoleOutput.push(args.map(String).join(' ')); + }); + console.error = jest.fn((...args: unknown[]) => { + consoleErrors.push(args.map(String).join(' ')); + }); +}); + +afterEach(() => { + console.log = originalLog; + console.error = originalError; +}); + +describe('formatOutput', () => { + describe('json format', () => { + it('should output JSON with indentation', () => { + formatOutput({ id: '123', name: 'Test' }, 'json'); + expect(consoleOutput[0]).toBe(JSON.stringify({ id: '123', name: 'Test' }, null, 2)); + }); + + it('should output JSON array', () => { + formatOutput([1, 2, 3], 'json'); + expect(consoleOutput[0]).toBe(JSON.stringify([1, 2, 3], null, 2)); + }); + + it('should output null as JSON', () => { + formatOutput(null, 'json'); + expect(consoleOutput[0]).toBe('null'); + }); + }); + + describe('yaml format', () => { + it('should output object in yaml-like format', () => { + formatOutput({ name: 'Test', id: '123' }, 'yaml'); + const output = consoleOutput.join('\n'); + expect(output).toContain('name: Test'); + expect(output).toContain('id: 123'); + }); + + it('should output array in yaml-like format', () => { + formatOutput(['a', 'b'], 'yaml'); + const output = consoleOutput.join('\n'); + expect(output).toContain('- a'); + expect(output).toContain('- b'); + }); + + it('should handle null', () => { + formatOutput(null, 'yaml'); + expect(consoleOutput[0]).toContain('null'); + }); + + it('should handle empty object', () => { + formatOutput({}, 'yaml'); + expect(consoleOutput[0]).toContain('{}'); + }); + + it('should handle empty array', () => { + formatOutput([], 'yaml'); + expect(consoleOutput[0]).toContain('[]'); + }); + }); + + describe('table format', () => { + it('should show "No data" for null', () => { + formatOutput(null, 'table'); + expect(consoleOutput[0]).toContain('No data'); + }); + + it('should show "No data" for undefined', () => { + formatOutput(undefined, 'table'); + expect(consoleOutput[0]).toContain('No data'); + }); + + it('should show "No items" for empty array', () => { + formatOutput([], 'table'); + expect(consoleOutput[0]).toContain('No items'); + }); + + it('should show "No items" for paginated response with empty items', () => { + formatOutput({ items: [], total: 0 }, 'table'); + expect(consoleOutput[0]).toContain('No items'); + }); + + it('should render array of objects as table', () => { + formatOutput( + [ + { id: '1', name: 'First', status: 'ACTIVE' }, + { id: '2', name: 'Second', status: 'PAUSED' }, + ], + 'table' + ); + const output = consoleOutput.join('\n'); + expect(output).toContain('id'); + expect(output).toContain('name'); + expect(output).toContain('First'); + expect(output).toContain('Second'); + }); + + it('should render paginated response with total count', () => { + formatOutput( + { + items: [{ id: '1', name: 'Test' }], + total: 100, + }, + 'table' + ); + const output = consoleOutput.join('\n'); + expect(output).toContain('1'); + expect(output).toContain('Test'); + expect(output).toContain('Showing 1 of 100'); + }); + + it('should render single object as vertical table', () => { + formatOutput({ id: '123', name: 'Test', status: 'ACTIVE' }, 'table'); + const output = consoleOutput.join('\n'); + expect(output).toContain('id'); + expect(output).toContain('123'); + expect(output).toContain('name'); + expect(output).toContain('Test'); + }); + + it('should render primitive values', () => { + formatOutput('hello world', 'table'); + expect(consoleOutput[0]).toBe('hello world'); + }); + + it('should use table format as default', () => { + formatOutput({ id: '123' }); + const output = consoleOutput.join('\n'); + expect(output).toContain('id'); + expect(output).toContain('123'); + }); + + it('should prioritize important columns in arrays', () => { + formatOutput( + [ + { + someField: 'x', + id: '1', + otherField: 'y', + name: 'Test', + status: 'ACTIVE', + createdAt: '2025-01-01', + }, + ], + 'table' + ); + const output = consoleOutput.join('\n'); + // id, name, status, createdAt should appear (priority keys) + expect(output).toContain('id'); + expect(output).toContain('name'); + }); + + it('should print primitives in array', () => { + formatOutput(['hello', 'world'], 'table'); + const output = consoleOutput.join('\n'); + expect(output).toContain('hello'); + expect(output).toContain('world'); + }); + }); +}); + +describe('printError', () => { + it('should print error message to stderr', () => { + printError('Something went wrong'); + expect(consoleErrors[0]).toContain('Error: Something went wrong'); + }); +}); + +describe('printSuccess', () => { + it('should print success message', () => { + printSuccess('Done!'); + expect(consoleOutput[0]).toContain('Done!'); + }); +}); + +describe('printWarning', () => { + it('should print warning message', () => { + printWarning('Be careful'); + expect(consoleOutput[0]).toContain('Warning: Be careful'); + }); +}); diff --git a/src/__tests__/cli/utils.test.ts b/src/__tests__/cli/utils.test.ts new file mode 100644 index 0000000..aa378f1 --- /dev/null +++ b/src/__tests__/cli/utils.test.ts @@ -0,0 +1,223 @@ +/** + * Tests for CLI utilities + */ + +import * as fs from 'fs'; +// os is used indirectly via path.join for config paths +import * as path from 'path'; +import { + loadConfig, + saveConfig, + clearConfig, + getConfigForDisplay, + createClient, + parseJsonArg, +} from '../../cli/utils'; + +// Mock fs +jest.mock('fs'); +const mockFs = jest.mocked(fs); + +// Mock os.homedir +jest.mock('os', () => ({ + ...jest.requireActual('os'), + homedir: jest.fn(() => '/mock/home'), +})); + +// Mock Scope3Client +jest.mock('../../client', () => ({ + Scope3Client: jest.fn().mockImplementation((config: Record) => ({ + config, + advertisers: {}, + campaigns: {}, + })), +})); + +const CONFIG_DIR = path.join('/mock/home', '.scope3'); +const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json'); + +describe('loadConfig', () => { + beforeEach(() => { + mockFs.existsSync.mockReset(); + mockFs.readFileSync.mockReset(); + }); + + it('should return empty config when file does not exist', () => { + mockFs.existsSync.mockReturnValue(false); + expect(loadConfig()).toEqual({}); + }); + + it('should return parsed config when file exists', () => { + const config = { apiKey: 'test-key', version: 'v2' }; + mockFs.existsSync.mockReturnValue(true); + mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); + + expect(loadConfig()).toEqual(config); + }); + + it('should return empty config on parse error', () => { + mockFs.existsSync.mockReturnValue(true); + mockFs.readFileSync.mockReturnValue('invalid json'); + + expect(loadConfig()).toEqual({}); + }); + + it('should return empty config on read error', () => { + mockFs.existsSync.mockReturnValue(true); + mockFs.readFileSync.mockImplementation(() => { + throw new Error('Permission denied'); + }); + + expect(loadConfig()).toEqual({}); + }); +}); + +describe('saveConfig', () => { + beforeEach(() => { + mockFs.existsSync.mockReset(); + mockFs.mkdirSync.mockReset(); + mockFs.writeFileSync.mockReset(); + }); + + it('should create directory if it does not exist', () => { + mockFs.existsSync.mockReturnValue(false); + + saveConfig({ apiKey: 'test-key' }); + + expect(mockFs.mkdirSync).toHaveBeenCalledWith(CONFIG_DIR, { recursive: true, mode: 0o700 }); + }); + + it('should not create directory if it exists', () => { + mockFs.existsSync.mockReturnValue(true); + + saveConfig({ apiKey: 'test-key' }); + + expect(mockFs.mkdirSync).not.toHaveBeenCalled(); + }); + + it('should write config with restricted permissions', () => { + mockFs.existsSync.mockReturnValue(true); + + saveConfig({ apiKey: 'test-key', version: 'v2' }); + + expect(mockFs.writeFileSync).toHaveBeenCalledWith( + CONFIG_FILE, + JSON.stringify({ apiKey: 'test-key', version: 'v2' }, null, 2), + { mode: 0o600 } + ); + }); +}); + +describe('clearConfig', () => { + beforeEach(() => { + mockFs.existsSync.mockReset(); + mockFs.unlinkSync.mockReset(); + }); + + it('should delete config file if it exists', () => { + mockFs.existsSync.mockReturnValue(true); + + clearConfig(); + + expect(mockFs.unlinkSync).toHaveBeenCalledWith(CONFIG_FILE); + }); + + it('should do nothing if config file does not exist', () => { + mockFs.existsSync.mockReturnValue(false); + + clearConfig(); + + expect(mockFs.unlinkSync).not.toHaveBeenCalled(); + }); +}); + +describe('getConfigForDisplay', () => { + it('should redact API key', () => { + const display = getConfigForDisplay({ apiKey: 'sk_1234567890abcdef' }); + expect(display.apiKey).toBe('sk_12345...cdef'); + expect(display.apiKey).not.toBe('sk_1234567890abcdef'); + }); + + it('should show undefined for missing API key', () => { + const display = getConfigForDisplay({}); + expect(display.apiKey).toBeUndefined(); + }); + + it('should show all config values', () => { + const display = getConfigForDisplay({ + apiKey: 'sk_1234567890abcdef', + version: 'v2', + environment: 'staging', + baseUrl: 'https://custom.com', + }); + + expect(display.version).toBe('v2'); + expect(display.environment).toBe('staging'); + expect(display.baseUrl).toBe('https://custom.com'); + }); +}); + +describe('createClient', () => { + const originalEnv = process.env; + + beforeEach(() => { + process.env = { ...originalEnv }; + mockFs.existsSync.mockReturnValue(false); // No config file + }); + + afterEach(() => { + process.env = originalEnv; + }); + + it('should throw when no API key is available', () => { + delete process.env.SCOPE3_API_KEY; + expect(() => createClient({})).toThrow('API key required'); + }); + + it('should use CLI flag API key first', () => { + process.env.SCOPE3_API_KEY = 'env-key'; + const client = createClient({ apiKey: 'cli-key' }); + expect(client).toBeDefined(); + }); + + it('should use env var API key as fallback', () => { + process.env.SCOPE3_API_KEY = 'env-key'; + const client = createClient({}); + expect(client).toBeDefined(); + }); + + it('should use config API key as second priority', () => { + mockFs.existsSync.mockReturnValue(true); + mockFs.readFileSync.mockReturnValue(JSON.stringify({ apiKey: 'config-key' })); + + const client = createClient({}); + expect(client).toBeDefined(); + }); + + it('should default version to v2', () => { + const client = createClient({ apiKey: 'test-key' }); + expect(client).toBeDefined(); + }); +}); + +describe('parseJsonArg', () => { + it('should parse valid JSON', () => { + expect(parseJsonArg('{"name":"Test"}')).toEqual({ name: 'Test' }); + }); + + it('should parse JSON array', () => { + expect(parseJsonArg('["a","b"]')).toEqual(['a', 'b']); + }); + + it('should return original string on parse failure', () => { + expect(parseJsonArg('not json')).toBe('not json'); + }); + + it('should parse JSON number', () => { + expect(parseJsonArg('42')).toBe(42); + }); + + it('should parse JSON boolean', () => { + expect(parseJsonArg('true')).toBe(true); + }); +}); diff --git a/src/__tests__/client-mcp.test.ts b/src/__tests__/client-mcp.test.ts deleted file mode 100644 index 498dad4..0000000 --- a/src/__tests__/client-mcp.test.ts +++ /dev/null @@ -1,386 +0,0 @@ -/** - * Tests for Scope3Client MCP protocol interactions - * - * Tests the actual MCP client behavior including: - * - structuredContent handling - * - Text content fallback - * - JSON parsing from text - * - Error scenarios - * - Debug mode - */ - -import { Scope3Client } from '../client'; -import { Client } from '@modelcontextprotocol/sdk/client/index.js'; -import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; - -// Mock the MCP SDK modules -jest.mock('@modelcontextprotocol/sdk/client/index.js'); -jest.mock('@modelcontextprotocol/sdk/client/streamableHttp.js'); - -describe('Scope3Client MCP Protocol', () => { - let client: Scope3Client; - let mockMcpClient: jest.Mocked; - let mockTransport: jest.Mocked; - let consoleErrorSpy: jest.SpyInstance; - - beforeEach(() => { - // Reset mocks - jest.clearAllMocks(); - - // Suppress logger output during tests - consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); - - // Setup mock MCP client - mockMcpClient = { - connect: jest.fn(), - close: jest.fn(), - callTool: jest.fn(), - } as unknown as jest.Mocked; - - mockTransport = { - close: jest.fn(), - } as unknown as jest.Mocked; - - // Mock constructor to return our mock client - (Client as jest.MockedClass).mockImplementation(() => mockMcpClient); - ( - StreamableHTTPClientTransport as jest.MockedClass - ).mockImplementation(() => mockTransport); - - client = new Scope3Client({ - apiKey: 'test-key', - environment: 'production', - }); - }); - - afterEach(async () => { - await client.disconnect(); - consoleErrorSpy.mockRestore(); - }); - - describe('connection management', () => { - it('should connect once on first callTool', async () => { - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: { result: 'success' }, - content: [], - }); - - await client['callTool']('test_tool', { arg: 'value' }); - - expect(mockMcpClient.connect).toHaveBeenCalledTimes(1); - expect(mockMcpClient.connect).toHaveBeenCalledWith(mockTransport); - }); - - it('should not reconnect on subsequent calls', async () => { - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: { result: 'success' }, - content: [], - }); - - await client['callTool']('test_tool_1', {}); - await client['callTool']('test_tool_2', {}); - - expect(mockMcpClient.connect).toHaveBeenCalledTimes(1); - }); - - it('should disconnect cleanly', async () => { - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: { result: 'success' }, - content: [], - }); - - await client['callTool']('test_tool', {}); - await client.disconnect(); - - expect(mockMcpClient.close).toHaveBeenCalledTimes(1); - expect(mockTransport.close).toHaveBeenCalledTimes(1); - }); - - it('should not error when disconnecting without connecting', async () => { - await expect(client.disconnect()).resolves.not.toThrow(); - expect(mockMcpClient.close).not.toHaveBeenCalled(); - }); - }); - - describe('structuredContent handling (preferred path)', () => { - it('should return structuredContent with message when text content present', async () => { - const expectedData = { id: '123', name: 'Test Campaign', status: 'active' }; - const textMessage = 'Campaign retrieved successfully'; - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: expectedData, - content: [{ type: 'text', text: textMessage }], - }); - - const result = await client['callTool'], typeof expectedData>( - 'campaigns_get', - { campaignId: '123' } - ); - - expect(result).toEqual({ _message: textMessage, ...expectedData }); - }); - - it('should return structuredContent without message when no text content', async () => { - const expectedData = { id: '123', name: 'Test Campaign', status: 'active' }; - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: expectedData, - content: [], - }); - - const result = await client['callTool'], typeof expectedData>( - 'campaigns_get', - { campaignId: '123' } - ); - - expect(result).toEqual(expectedData); - }); - - it('should handle complex nested structuredContent', async () => { - const complexData = { - items: [ - { id: '1', nested: { deep: { value: 'test' } } }, - { id: '2', array: [1, 2, 3] }, - ], - metadata: { total: 2, page: 1 }, - }; - - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: complexData, - content: [], - }); - - const result = await client['callTool']('campaigns_list', {}); - - expect(result).toEqual(complexData); - }); - - it('should handle empty structuredContent object', async () => { - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: {}, - content: [], - }); - - const result = await client['callTool']('test_tool', {}); - - expect(result).toEqual({}); - }); - }); - - describe('API specification violations', () => { - it('should throw error when JSON is in text content instead of structuredContent', async () => { - const data = { id: '456', status: 'completed' }; - mockMcpClient.callTool.mockResolvedValue({ - content: [{ type: 'text', text: JSON.stringify(data) }], - }); - - await expect(client['callTool']('test_tool', {})).rejects.toThrow( - 'API Error: Missing structured data' - ); - await expect(client['callTool']('test_tool', {})).rejects.toThrow( - 'This is an API bug that needs to be fixed upstream' - ); - }); - - it('should throw error when array is in text content instead of structuredContent', async () => { - const data = [{ id: '1' }, { id: '2' }]; - mockMcpClient.callTool.mockResolvedValue({ - content: [{ type: 'text', text: JSON.stringify(data) }], - }); - - await expect(client['callTool']('test_tool', {})).rejects.toThrow( - 'API Error: Missing structured data' - ); - }); - - it('should throw error when plain text is returned without structuredContent', async () => { - const plainText = 'Operation completed successfully'; - mockMcpClient.callTool.mockResolvedValue({ - content: [{ type: 'text', text: plainText }], - }); - - await expect(client['callTool']('test_tool', {})).rejects.toThrow( - 'API Error: Missing structured data' - ); - }); - - it('should include debug info in error when structuredContent is missing', async () => { - mockMcpClient.callTool.mockResolvedValue({ - content: [{ type: 'text', text: 'some data' }], - }); - - await expect(client['callTool']('test_tool', {})).rejects.toThrow('test_tool'); - await expect(client['callTool']('test_tool', {})).rejects.toThrow('API Error'); - }); - }); - - describe('error handling', () => { - it('should throw error when no content is returned', async () => { - mockMcpClient.callTool.mockResolvedValue({ - content: [], - }); - - await expect(client['callTool']('test_tool', {})).rejects.toThrow( - 'API Error: Missing structured data' - ); - }); - - it('should throw error when content type is not text', async () => { - mockMcpClient.callTool.mockResolvedValue({ - content: [{ type: 'image', data: 'base64data' }], - }); - - await expect(client['callTool']('test_tool', {})).rejects.toThrow( - 'API Error: Missing structured data' - ); - }); - - it('should propagate MCP client errors', async () => { - const mcpError = new Error('MCP transport failure'); - mockMcpClient.callTool.mockRejectedValue(mcpError); - - await expect(client['callTool']('test_tool', {})).rejects.toThrow('MCP transport failure'); - }); - - it('should handle connection errors', async () => { - const connectionError = new Error('Connection refused'); - mockMcpClient.connect.mockRejectedValue(connectionError); - - await expect(client['callTool']('test_tool', {})).rejects.toThrow('Connection refused'); - }); - }); - - describe('debug mode', () => { - beforeEach(() => { - // Create client with debug enabled - client = new Scope3Client({ - apiKey: 'test-key', - debug: true, - }); - - // Re-mock after new client creation - (Client as jest.MockedClass).mockImplementation(() => mockMcpClient); - ( - StreamableHTTPClientTransport as jest.MockedClass - ).mockImplementation(() => mockTransport); - }); - - it('should store debug info when debug mode is enabled', async () => { - const request = { campaignId: '123' }; - const response = { id: '123', name: 'Test' }; - - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: response, - content: [], - }); - - await client['callTool']('campaigns_get', request); - - expect(client.lastDebugInfo).toBeDefined(); - expect(client.lastDebugInfo?.toolName).toBe('campaigns_get'); - expect(client.lastDebugInfo?.request).toEqual(request); - expect(client.lastDebugInfo?.response).toEqual(response); - expect(client.lastDebugInfo?.durationMs).toBeGreaterThanOrEqual(0); - }); - - it('should not store debug info when API violates spec (no structuredContent)', async () => { - const data = { id: '456' }; - const rawText = JSON.stringify(data); - - mockMcpClient.callTool.mockResolvedValue({ - content: [{ type: 'text', text: rawText }], - }); - - // Should throw before storing debug info - await expect(client['callTool']('test_tool', {})).rejects.toThrow( - 'API Error: Missing structured data' - ); - }); - - it('should not store debug info when debug mode is disabled', async () => { - const regularClient = new Scope3Client({ - apiKey: 'test-key', - debug: false, - }); - - (Client as jest.MockedClass).mockImplementation(() => mockMcpClient); - ( - StreamableHTTPClientTransport as jest.MockedClass - ).mockImplementation(() => mockTransport); - - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: { result: 'success' }, - content: [], - }); - - await regularClient['callTool']('test_tool', {}); - - expect(regularClient.lastDebugInfo).toBeUndefined(); - }); - }); - - describe('environment and URL configuration', () => { - it('should use production URL by default', () => { - const prodClient = new Scope3Client({ - apiKey: 'test-key', - }); - - expect(prodClient.getBaseUrl()).toBe('https://api.agentic.scope3.com'); - }); - - it('should use staging URL when environment is staging', () => { - const stagingClient = new Scope3Client({ - apiKey: 'test-key', - environment: 'staging', - }); - - expect(stagingClient.getBaseUrl()).toBe('https://api.agentic.staging.scope3.com'); - }); - - it('should use custom baseUrl when provided (overrides environment)', () => { - const customClient = new Scope3Client({ - apiKey: 'test-key', - environment: 'staging', - baseUrl: 'https://custom.api.com', - }); - - expect(customClient.getBaseUrl()).toBe('https://custom.api.com'); - }); - }); - - describe('request argument handling', () => { - it('should pass arguments as Record', async () => { - const args = { - stringArg: 'test', - numberArg: 123, - boolArg: true, - objectArg: { nested: 'value' }, - arrayArg: [1, 2, 3], - }; - - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: { success: true }, - content: [], - }); - - await client['callTool']('test_tool', args); - - expect(mockMcpClient.callTool).toHaveBeenCalledWith({ - name: 'test_tool', - arguments: args, - }); - }); - - it('should handle empty arguments object', async () => { - mockMcpClient.callTool.mockResolvedValue({ - structuredContent: { success: true }, - content: [], - }); - - await client['callTool']('test_tool', {}); - - expect(mockMcpClient.callTool).toHaveBeenCalledWith({ - name: 'test_tool', - arguments: {}, - }); - }); - }); -}); diff --git a/src/__tests__/client.test.ts b/src/__tests__/client.test.ts index 2ed9ce3..6de84d0 100644 --- a/src/__tests__/client.test.ts +++ b/src/__tests__/client.test.ts @@ -1,47 +1,224 @@ -import { PlatformClient } from '../platform-client'; +/** + * Tests for Scope3Client + */ -describe('PlatformClient', () => { - let client: PlatformClient; +import { Scope3Client } from '../client'; - beforeEach(() => { - client = new PlatformClient({ - apiKey: 'test-api-key', +describe('Scope3Client', () => { + describe('initialization', () => { + it('should require apiKey', () => { + expect(() => new Scope3Client({ apiKey: '', persona: 'buyer' })).toThrow( + 'apiKey is required' + ); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + expect(() => new Scope3Client({} as any)).toThrow('apiKey is required'); + }); + + it('should require persona', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + expect(() => new Scope3Client({ apiKey: 'test-key' } as any)).toThrow('persona is required'); + }); + + it('should default to v2 version', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.version).toBe('v2'); + }); + + it('should allow custom version', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer', version: 'v1' }); + expect(client.version).toBe('v1'); + }); + + it('should default to production base URL', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.baseUrl).toBe('https://api.agentic.scope3.com'); + }); + + it('should use staging URL when environment is staging', () => { + const client = new Scope3Client({ + apiKey: 'test-key', + persona: 'buyer', + environment: 'staging', + }); + expect(client.baseUrl).toBe('https://api.agentic.staging.scope3.com'); + }); + + it('should allow custom base URL', () => { + const client = new Scope3Client({ + apiKey: 'test-key', + persona: 'buyer', + baseUrl: 'https://custom.api.com', + }); + expect(client.baseUrl).toBe('https://custom.api.com'); + }); + + it('should remove trailing slash from base URL', () => { + const client = new Scope3Client({ + apiKey: 'test-key', + persona: 'buyer', + baseUrl: 'https://custom.api.com/', + }); + expect(client.baseUrl).toBe('https://custom.api.com'); + }); + + it('should store persona', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.persona).toBe('buyer'); }); }); - it('should initialize with default production URL', () => { - expect(client).toBeDefined(); + describe('buyer persona resources', () => { + it('should have advertisers resource', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.advertisers).toBeDefined(); + expect(typeof client.advertisers.list).toBe('function'); + expect(typeof client.advertisers.get).toBe('function'); + expect(typeof client.advertisers.create).toBe('function'); + expect(typeof client.advertisers.update).toBe('function'); + expect(typeof client.advertisers.delete).toBe('function'); + expect(typeof client.advertisers.brand).toBe('function'); + }); + + it('should have campaigns resource with type-specific methods', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.campaigns).toBeDefined(); + expect(typeof client.campaigns.list).toBe('function'); + expect(typeof client.campaigns.get).toBe('function'); + expect(typeof client.campaigns.createBundle).toBe('function'); + expect(typeof client.campaigns.updateBundle).toBe('function'); + expect(typeof client.campaigns.createPerformance).toBe('function'); + expect(typeof client.campaigns.updatePerformance).toBe('function'); + expect(typeof client.campaigns.createAudience).toBe('function'); + expect(typeof client.campaigns.execute).toBe('function'); + expect(typeof client.campaigns.pause).toBe('function'); + }); + + it('should return linked brand resource for advertiser with get, link, unlink', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + const brand = client.advertisers.brand('adv-123'); + expect(brand).toBeDefined(); + expect(typeof brand.get).toBe('function'); + expect(typeof brand.link).toBe('function'); + expect(typeof brand.unlink).toBe('function'); + }); + + it('should have bundles resource', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.bundles).toBeDefined(); + expect(typeof client.bundles.create).toBe('function'); + expect(typeof client.bundles.discoverProducts).toBe('function'); + expect(typeof client.bundles.browseProducts).toBe('function'); + expect(typeof client.bundles.products).toBe('function'); + }); + + it('should return products resource for bundle with list, add, remove', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + const products = client.bundles.products('bundle-123'); + expect(products).toBeDefined(); + expect(typeof products.list).toBe('function'); + expect(typeof products.add).toBe('function'); + expect(typeof products.remove).toBe('function'); + }); + + it('should have signals resource', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.signals).toBeDefined(); + expect(typeof client.signals.discover).toBe('function'); + expect(typeof client.signals.list).toBe('function'); + }); + + it('should have buyerBrands resource', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.buyerBrands).toBeDefined(); + expect(typeof client.buyerBrands.list).toBe('function'); + }); + }); + + describe('brand persona resources', () => { + it('should have brands resource', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'brand' }); + expect(client.brands).toBeDefined(); + expect(typeof client.brands.list).toBe('function'); + expect(typeof client.brands.get).toBe('function'); + expect(typeof client.brands.create).toBe('function'); + expect(typeof client.brands.update).toBe('function'); + expect(typeof client.brands.delete).toBe('function'); + }); + + it('should NOT have advertisers', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'brand' }); + expect(() => client.advertisers).toThrow( + 'advertisers is only available with the buyer persona' + ); + }); + + it('should NOT have campaigns', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'brand' }); + expect(() => client.campaigns).toThrow('campaigns is only available with the buyer persona'); + }); + }); + + describe('partner persona resources', () => { + it('should have health resource', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'partner' }); + expect(client.health).toBeDefined(); + expect(typeof client.health.check).toBe('function'); + }); + + it('should NOT have advertisers', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'partner' }); + expect(() => client.advertisers).toThrow( + 'advertisers is only available with the buyer persona' + ); + }); + + it('should NOT have campaigns', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'partner' }); + expect(() => client.campaigns).toThrow('campaigns is only available with the buyer persona'); + }); }); - it('should have all resource modules', () => { - expect(client.agents).toBeDefined(); - expect(client.assets).toBeDefined(); - expect(client.brandAgents).toBeDefined(); - expect(client.brandStandards).toBeDefined(); - expect(client.brandStories).toBeDefined(); - expect(client.campaigns).toBeDefined(); - expect(client.channels).toBeDefined(); - expect(client.creatives).toBeDefined(); - expect(client.tactics).toBeDefined(); - expect(client.mediaBuys).toBeDefined(); - expect(client.mediaProducts).toBeDefined(); - expect(client.agents).toBeDefined(); - expect(client.targeting).toBeDefined(); + describe('adapter selection', () => { + it('should default to REST adapter', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.baseUrl).toBe('https://api.agentic.scope3.com'); + }); + + it('should use MCP adapter when specified', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer', adapter: 'mcp' }); + expect(client.baseUrl).toBe('https://api.agentic.scope3.com'); + }); }); - it('should accept custom base URL', () => { - const customClient = new PlatformClient({ - apiKey: 'test-api-key', - baseUrl: 'https://custom.api.com', + describe('version handling', () => { + it('should support latest version', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer', version: 'latest' }); + expect(client.version).toBe('latest'); + }); + + it('should support v1 version', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer', version: 'v1' }); + expect(client.version).toBe('v1'); + }); + }); + + describe('connect/disconnect', () => { + it('should connect and disconnect without error for REST', async () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + await expect(client.connect()).resolves.toBeUndefined(); + await expect(client.disconnect()).resolves.toBeUndefined(); }); - expect(customClient).toBeDefined(); }); - it('should accept custom timeout', () => { - const customClient = new PlatformClient({ - apiKey: 'test-api-key', - timeout: 60000, + describe('debug mode', () => { + it('should default to debug off', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer' }); + expect(client.debug).toBe(false); + }); + + it('should enable debug when specified', () => { + const client = new Scope3Client({ apiKey: 'test-key', persona: 'buyer', debug: true }); + expect(client.debug).toBe(true); }); - expect(customClient).toBeDefined(); }); }); diff --git a/src/__tests__/resources/advertisers.test.ts b/src/__tests__/resources/advertisers.test.ts new file mode 100644 index 0000000..473485a --- /dev/null +++ b/src/__tests__/resources/advertisers.test.ts @@ -0,0 +1,129 @@ +/** + * Tests for AdvertisersResource + */ + +import { AdvertisersResource } from '../../resources/advertisers'; +import type { BaseAdapter } from '../../adapters/base'; + +describe('AdvertisersResource', () => { + let mockAdapter: jest.Mocked; + let resource: AdvertisersResource; + + beforeEach(() => { + mockAdapter = { + baseUrl: 'https://api.test.com', + version: 'v2', + persona: 'buyer' as const, + debug: false, + request: jest.fn(), + connect: jest.fn(), + disconnect: jest.fn(), + }; + resource = new AdvertisersResource(mockAdapter); + }); + + describe('list', () => { + it('should call adapter with correct path', async () => { + mockAdapter.request.mockResolvedValue({ items: [], total: 0 }); + + await resource.list(); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/advertisers', undefined, { + params: { take: undefined, skip: undefined, status: undefined, name: undefined }, + }); + }); + + it('should pass pagination and filter params', async () => { + mockAdapter.request.mockResolvedValue({ items: [], total: 0 }); + + await resource.list({ take: 10, skip: 20, status: 'ACTIVE', name: 'Acme' }); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/advertisers', undefined, { + params: { take: 10, skip: 20, status: 'ACTIVE', name: 'Acme' }, + }); + }); + }); + + describe('get', () => { + it('should call adapter with correct path', async () => { + mockAdapter.request.mockResolvedValue({ id: '123', name: 'Test' }); + + await resource.get('123'); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/advertisers/123'); + }); + }); + + describe('create', () => { + it('should call adapter with correct path and body', async () => { + mockAdapter.request.mockResolvedValue({ id: '123', name: 'New Advertiser' }); + + await resource.create({ name: 'New Advertiser', description: 'Test desc' }); + + expect(mockAdapter.request).toHaveBeenCalledWith('POST', '/advertisers', { + name: 'New Advertiser', + description: 'Test desc', + }); + }); + }); + + describe('update', () => { + it('should call adapter with correct path and body', async () => { + mockAdapter.request.mockResolvedValue({ id: '123', name: 'Updated' }); + + await resource.update('123', { name: 'Updated' }); + + expect(mockAdapter.request).toHaveBeenCalledWith('PUT', '/advertisers/123', { + name: 'Updated', + }); + }); + }); + + describe('delete', () => { + it('should call adapter with correct path', async () => { + mockAdapter.request.mockResolvedValue(undefined); + + await resource.delete('123'); + + expect(mockAdapter.request).toHaveBeenCalledWith('DELETE', '/advertisers/123'); + }); + }); + + describe('brand', () => { + it('should return BuyerLinkedBrandResource for advertiser with get, link, unlink', () => { + const brand = resource.brand('adv-123'); + + expect(brand).toBeDefined(); + expect(typeof brand.get).toBe('function'); + expect(typeof brand.link).toBe('function'); + expect(typeof brand.unlink).toBe('function'); + }); + }); + + describe('sub-resources', () => { + it('should return conversionEvents resource for advertiser', () => { + const convEvents = resource.conversionEvents('adv-123'); + expect(convEvents).toBeDefined(); + }); + + it('should return creativeSets resource for advertiser', () => { + const creativeSets = resource.creativeSets('adv-123'); + expect(creativeSets).toBeDefined(); + }); + + it('should return testCohorts resource for advertiser', () => { + const testCohorts = resource.testCohorts('adv-123'); + expect(testCohorts).toBeDefined(); + }); + + it('should return reporting resource for advertiser', () => { + const reporting = resource.reporting('adv-123'); + expect(reporting).toBeDefined(); + }); + + it('should return mediaBuys resource for advertiser', () => { + const mediaBuys = resource.mediaBuys('adv-123'); + expect(mediaBuys).toBeDefined(); + }); + }); +}); diff --git a/src/__tests__/resources/brands.test.ts b/src/__tests__/resources/brands.test.ts new file mode 100644 index 0000000..b244b3b --- /dev/null +++ b/src/__tests__/resources/brands.test.ts @@ -0,0 +1,115 @@ +/** + * Tests for BuyerBrandsResource and BuyerLinkedBrandResource + */ + +import { BuyerBrandsResource, BuyerLinkedBrandResource } from '../../resources/brands'; +import type { BaseAdapter } from '../../adapters/base'; + +describe('BuyerBrandsResource', () => { + let mockAdapter: jest.Mocked; + let resource: BuyerBrandsResource; + + beforeEach(() => { + mockAdapter = { + baseUrl: 'https://api.test.com', + version: 'v2', + persona: 'buyer' as const, + debug: false, + request: jest.fn(), + connect: jest.fn(), + disconnect: jest.fn(), + }; + resource = new BuyerBrandsResource(mockAdapter); + }); + + describe('list', () => { + it('should call adapter with correct path', async () => { + mockAdapter.request.mockResolvedValue({ data: [], pagination: {} }); + + await resource.list(); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/brands', undefined, { + params: { take: undefined, skip: undefined, status: undefined, name: undefined }, + }); + }); + + it('should pass filter params', async () => { + mockAdapter.request.mockResolvedValue({ data: [], pagination: {} }); + + await resource.list({ take: 10, skip: 0, status: 'ACTIVE', name: 'Acme' }); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/brands', undefined, { + params: { take: 10, skip: 0, status: 'ACTIVE', name: 'Acme' }, + }); + }); + }); +}); + +describe('BuyerLinkedBrandResource', () => { + let mockAdapter: jest.Mocked; + let resource: BuyerLinkedBrandResource; + + beforeEach(() => { + mockAdapter = { + baseUrl: 'https://api.test.com', + version: 'v2', + persona: 'buyer' as const, + debug: false, + request: jest.fn(), + connect: jest.fn(), + disconnect: jest.fn(), + }; + resource = new BuyerLinkedBrandResource(mockAdapter, 'adv-123'); + }); + + describe('get', () => { + it('should call adapter with correct path', async () => { + mockAdapter.request.mockResolvedValue({ brandId: 'brand-1', advertiserId: 'adv-123' }); + + await resource.get(); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/advertisers/adv-123/brand'); + }); + + it('should return linked brand data', async () => { + const linkedBrand = { brandId: 'brand-1', advertiserId: 'adv-123' }; + mockAdapter.request.mockResolvedValue(linkedBrand); + + const result = await resource.get(); + + expect(result).toEqual(linkedBrand); + }); + }); + + describe('link', () => { + it('should call adapter with PUT and body', async () => { + const input = { brandId: 'brand-123' }; + mockAdapter.request.mockResolvedValue({ brandId: 'brand-123', advertiserId: 'adv-123' }); + + await resource.link(input); + + expect(mockAdapter.request).toHaveBeenCalledWith('PUT', '/advertisers/adv-123/brand', input); + }); + }); + + describe('unlink', () => { + it('should call adapter with DELETE', async () => { + mockAdapter.request.mockResolvedValue(undefined); + + await resource.unlink(); + + expect(mockAdapter.request).toHaveBeenCalledWith('DELETE', '/advertisers/adv-123/brand'); + }); + }); + + describe('scoping', () => { + it('should use the correct advertiser ID in all paths', async () => { + const resource2 = new BuyerLinkedBrandResource(mockAdapter, 'different-adv'); + mockAdapter.request.mockResolvedValue({}); + + await resource2.get(); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/advertisers/different-adv/brand'); + }); + }); +}); diff --git a/src/__tests__/resources/campaigns.test.ts b/src/__tests__/resources/campaigns.test.ts new file mode 100644 index 0000000..5ab2117 --- /dev/null +++ b/src/__tests__/resources/campaigns.test.ts @@ -0,0 +1,170 @@ +/** + * Tests for CampaignsResource + */ + +import { CampaignsResource } from '../../resources/campaigns'; +import type { BaseAdapter } from '../../adapters/base'; + +describe('CampaignsResource', () => { + let mockAdapter: jest.Mocked; + let resource: CampaignsResource; + + beforeEach(() => { + mockAdapter = { + baseUrl: 'https://api.test.com', + version: 'v2', + persona: 'buyer' as const, + debug: false, + request: jest.fn(), + connect: jest.fn(), + disconnect: jest.fn(), + }; + resource = new CampaignsResource(mockAdapter); + }); + + describe('list', () => { + it('should call adapter with correct path', async () => { + mockAdapter.request.mockResolvedValue({ items: [], total: 0 }); + + await resource.list(); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/campaigns', undefined, { + params: { + take: undefined, + skip: undefined, + advertiserId: undefined, + type: undefined, + status: undefined, + }, + }); + }); + + it('should pass filter params including type', async () => { + mockAdapter.request.mockResolvedValue({ items: [], total: 0 }); + + await resource.list({ advertiserId: 'adv-123', status: 'ACTIVE', type: 'bundle' }); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/campaigns', undefined, { + params: { + take: undefined, + skip: undefined, + advertiserId: 'adv-123', + type: 'bundle', + status: 'ACTIVE', + }, + }); + }); + }); + + describe('get', () => { + it('should call adapter with correct path', async () => { + mockAdapter.request.mockResolvedValue({ id: 'camp-123', name: 'Test Campaign' }); + + await resource.get('camp-123'); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/campaigns/camp-123'); + }); + }); + + describe('createBundle', () => { + it('should call adapter with POST /campaigns/bundle', async () => { + const input = { + advertiserId: 'adv-123', + name: 'Q1 Campaign', + bundleId: 'bundle-456', + flightDates: { startDate: '2025-01-01', endDate: '2025-03-31' }, + budget: { total: 50000, currency: 'USD' }, + }; + + mockAdapter.request.mockResolvedValue({ id: 'camp-123', ...input }); + + await resource.createBundle(input); + + expect(mockAdapter.request).toHaveBeenCalledWith('POST', '/campaigns/bundle', input); + }); + }); + + describe('updateBundle', () => { + it('should call adapter with PUT /campaigns/bundle/{id}', async () => { + mockAdapter.request.mockResolvedValue({ id: 'camp-123', name: 'Updated' }); + + await resource.updateBundle('camp-123', { name: 'Updated' }); + + expect(mockAdapter.request).toHaveBeenCalledWith('PUT', '/campaigns/bundle/camp-123', { + name: 'Updated', + }); + }); + }); + + describe('createPerformance', () => { + it('should call adapter with POST /campaigns/performance', async () => { + const input = { + advertiserId: 'adv-123', + name: 'Q1 ROAS', + flightDates: { startDate: '2025-01-01', endDate: '2025-03-31' }, + budget: { total: 100000, currency: 'USD' }, + performanceConfig: { objective: 'ROAS' as const, goals: { targetRoas: 4.0 } }, + }; + + mockAdapter.request.mockResolvedValue({ id: 'camp-456', ...input }); + + await resource.createPerformance(input); + + expect(mockAdapter.request).toHaveBeenCalledWith('POST', '/campaigns/performance', input); + }); + }); + + describe('updatePerformance', () => { + it('should call adapter with PUT /campaigns/performance/{id}', async () => { + const update = { performanceConfig: { goals: { targetRoas: 5.0 } } }; + mockAdapter.request.mockResolvedValue({ id: 'camp-456' }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await resource.updatePerformance('camp-456', update as any); + + expect(mockAdapter.request).toHaveBeenCalledWith( + 'PUT', + '/campaigns/performance/camp-456', + update + ); + }); + }); + + describe('createAudience', () => { + it('should call adapter with POST /campaigns/audience', async () => { + const input = { + advertiserId: 'adv-123', + name: 'Audience Campaign', + flightDates: { startDate: '2025-01-01', endDate: '2025-03-31' }, + budget: { total: 25000, currency: 'USD' }, + signals: ['signal-1'], + }; + + mockAdapter.request.mockResolvedValue({ id: 'camp-789', ...input }); + + await resource.createAudience(input); + + expect(mockAdapter.request).toHaveBeenCalledWith('POST', '/campaigns/audience', input); + }); + }); + + describe('execute', () => { + it('should call execute endpoint', async () => { + mockAdapter.request.mockResolvedValue({ success: true, executedAt: '2025-01-01' }); + + await resource.execute('camp-123'); + + expect(mockAdapter.request).toHaveBeenCalledWith('POST', '/campaigns/camp-123/execute'); + }); + }); + + describe('pause', () => { + it('should call pause endpoint', async () => { + mockAdapter.request.mockResolvedValue({ id: 'camp-123', status: 'PAUSED' }); + + await resource.pause('camp-123'); + + expect(mockAdapter.request).toHaveBeenCalledWith('POST', '/campaigns/camp-123/pause'); + }); + }); +}); diff --git a/src/__tests__/resources/products.test.ts b/src/__tests__/resources/products.test.ts new file mode 100644 index 0000000..2498612 --- /dev/null +++ b/src/__tests__/resources/products.test.ts @@ -0,0 +1,98 @@ +/** + * Tests for BundleProductsResource + */ + +import { BundleProductsResource } from '../../resources/products'; +import type { BaseAdapter } from '../../adapters/base'; + +describe('BundleProductsResource', () => { + let mockAdapter: jest.Mocked; + let resource: BundleProductsResource; + + beforeEach(() => { + mockAdapter = { + baseUrl: 'https://api.test.com', + version: 'v2', + persona: 'buyer' as const, + debug: false, + request: jest.fn(), + connect: jest.fn(), + disconnect: jest.fn(), + }; + resource = new BundleProductsResource(mockAdapter, 'bundle-123'); + }); + + describe('list', () => { + it('should call adapter with GET /bundles/{bundleId}/products', async () => { + mockAdapter.request.mockResolvedValue({ + bundleId: 'bundle-123', + products: [], + totalProducts: 0, + }); + + await resource.list(); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/bundles/bundle-123/products'); + }); + }); + + describe('add', () => { + it('should call adapter with POST /bundles/{bundleId}/products and products array', async () => { + const input = { + products: [ + { + productId: 'prod-1', + salesAgentId: 'agent-1', + groupId: 'group-0', + groupName: 'Publisher A', + cpm: 12.5, + budget: 5000, + }, + ], + }; + mockAdapter.request.mockResolvedValue({ + bundleId: 'bundle-123', + products: input.products, + totalProducts: 1, + }); + + await resource.add(input); + + expect(mockAdapter.request).toHaveBeenCalledWith( + 'POST', + '/bundles/bundle-123/products', + input + ); + }); + }); + + describe('remove', () => { + it('should call adapter with DELETE /bundles/{bundleId}/products and productIds', async () => { + const input = { productIds: ['prod-1', 'prod-2'] }; + mockAdapter.request.mockResolvedValue(undefined); + + await resource.remove(input); + + expect(mockAdapter.request).toHaveBeenCalledWith( + 'DELETE', + '/bundles/bundle-123/products', + input + ); + }); + }); + + describe('scoping', () => { + it('should use the correct bundle ID in all paths', async () => { + const resource2 = new BundleProductsResource(mockAdapter, 'different-bundle'); + mockAdapter.request.mockResolvedValue({ + bundleId: 'different-bundle', + products: [], + totalProducts: 0, + }); + + await resource2.list(); + + expect(mockAdapter.request).toHaveBeenCalledWith('GET', '/bundles/different-bundle/products'); + }); + }); +}); diff --git a/src/__tests__/skill/fetcher.test.ts b/src/__tests__/skill/fetcher.test.ts new file mode 100644 index 0000000..6111405 --- /dev/null +++ b/src/__tests__/skill/fetcher.test.ts @@ -0,0 +1,166 @@ +/** + * Tests for skill.md fetcher + */ + +import { fetchSkillMd, getBundledSkillMd } from '../../skill/fetcher'; +import { getBundledSkillMd as getBundledSkillMdFromBundled } from '../../skill/bundled'; + +// Mock fetch +const mockFetch = jest.fn(); +global.fetch = mockFetch; + +// Suppress console.warn in tests +const originalWarn = console.warn; +beforeAll(() => { + console.warn = jest.fn(); +}); +afterAll(() => { + console.warn = originalWarn; +}); + +const baseUrl = 'https://api.agentic.scope3.com'; + +describe('fetchSkillMd', () => { + beforeEach(() => { + mockFetch.mockReset(); + }); + + it('should fetch skill.md with default options (v2, buyer persona)', async () => { + mockFetch.mockResolvedValue({ + ok: true, + text: () => Promise.resolve('# Skill v2'), + }); + + const result = await fetchSkillMd(); + + expect(mockFetch).toHaveBeenCalledWith( + `${baseUrl}/api/v2/buyer/skill.md`, + expect.objectContaining({ + headers: { Accept: 'text/markdown, text/plain, */*' }, + }) + ); + expect(result).toBe('# Skill v2'); + }); + + it('should fetch v1 skill.md when specified', async () => { + mockFetch.mockResolvedValue({ + ok: true, + text: () => Promise.resolve('# Skill v1'), + }); + + await fetchSkillMd({ version: 'v1' }); + + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/v1/buyer/skill.md`, expect.anything()); + }); + + it('should fetch latest skill.md (maps to v2)', async () => { + mockFetch.mockResolvedValue({ + ok: true, + text: () => Promise.resolve('# Skill latest'), + }); + + await fetchSkillMd({ version: 'latest' }); + + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/v2/buyer/skill.md`, expect.anything()); + }); + + it('should use custom base URL', async () => { + mockFetch.mockResolvedValue({ + ok: true, + text: () => Promise.resolve('# Custom'), + }); + + await fetchSkillMd({ baseUrl: 'https://custom.com' }); + + expect(mockFetch).toHaveBeenCalledWith( + 'https://custom.com/api/v2/buyer/skill.md', + expect.anything() + ); + }); + + it('should fetch brand persona skill.md', async () => { + mockFetch.mockResolvedValue({ + ok: true, + text: () => Promise.resolve('# Brand Skill'), + }); + + await fetchSkillMd({ persona: 'brand' }); + + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/v2/brand/skill.md`, expect.anything()); + }); + + it('should fall back to bundled buyer skill on non-200 response', async () => { + mockFetch.mockResolvedValue({ + ok: false, + status: 404, + }); + + const result = await fetchSkillMd(); + + expect(result).toBe(getBundledSkillMdFromBundled('buyer')); + }); + + it('should fall back to bundled skill on network error', async () => { + mockFetch.mockRejectedValue(new Error('Network error')); + + const result = await fetchSkillMd(); + + expect(result).toBe(getBundledSkillMdFromBundled('buyer')); + }); + + it('should fall back to bundled skill on timeout', async () => { + const abortError = new Error('The operation was aborted'); + abortError.name = 'AbortError'; + mockFetch.mockRejectedValue(abortError); + + const result = await fetchSkillMd(); + + expect(result).toBe(getBundledSkillMdFromBundled('buyer')); + }); + + it('should fall back to bundled skill on non-Error throw', async () => { + mockFetch.mockRejectedValue('string error'); + + const result = await fetchSkillMd(); + + expect(result).toBe(getBundledSkillMdFromBundled('buyer')); + }); + + it('should fall back to bundled brand skill on non-200 for brand persona', async () => { + mockFetch.mockResolvedValue({ + ok: false, + status: 500, + }); + + const result = await fetchSkillMd({ persona: 'brand' }); + + expect(result).toBe(getBundledSkillMdFromBundled('brand')); + }); +}); + +describe('getBundledSkillMd', () => { + it('should return buyer skill.md content by default', () => { + const result = getBundledSkillMd(); + expect(result).toBe(getBundledSkillMdFromBundled('buyer')); + }); + + it('should return buyer skill.md content with buyer persona', () => { + const result = getBundledSkillMd('buyer'); + expect(result).toContain('scope3-agentic-buyer'); + }); + + it('should return brand skill.md content with brand persona', () => { + const result = getBundledSkillMd('brand'); + expect(result).toContain('scope3-agentic-brand'); + }); + + it('should return partner skill.md content with partner persona', () => { + const result = getBundledSkillMd('partner'); + expect(result).toContain('scope3-agentic-partner'); + }); + + it('should contain expected version header', () => { + const result = getBundledSkillMd('buyer'); + expect(result).toContain('2.0.0'); + }); +}); diff --git a/src/__tests__/skill/parser.test.ts b/src/__tests__/skill/parser.test.ts new file mode 100644 index 0000000..562a16e --- /dev/null +++ b/src/__tests__/skill/parser.test.ts @@ -0,0 +1,125 @@ +/** + * Tests for skill.md parser + */ + +import { parseSkillMd } from '../../skill/parser'; + +describe('parseSkillMd', () => { + const sampleSkillMd = `\`\`\`yaml +name: scope3-agentic +version: 2.0.0 +description: Scope3 Agentic API +api_base: https://api.agentic.scope3.com/api/v2 +\`\`\` + +## Overview + +The API for programmatic advertising. + +## Advertisers + +| Method | Endpoint | Description | +|--------|----------|-------------| +| GET | /advertisers | List all advertisers | +| POST | /advertisers | Create a new advertiser | +| GET | /advertisers/{id} | Get advertiser by ID | + +## MCP Tools + +| Tool | Operations | +|------|------------| +| \`manage_advertiser\` | create, get, update, list, delete | + +### Example + +\`\`\`bash +curl https://api.example.com/advertisers +\`\`\` +`; + + describe('header parsing', () => { + it('should parse name from yaml header', () => { + const result = parseSkillMd(sampleSkillMd); + expect(result.name).toBe('scope3-agentic'); + }); + + it('should parse version from yaml header', () => { + const result = parseSkillMd(sampleSkillMd); + expect(result.version).toBe('2.0.0'); + }); + + it('should parse description from yaml header', () => { + const result = parseSkillMd(sampleSkillMd); + expect(result.description).toBe('Scope3 Agentic API'); + }); + + it('should parse api_base from yaml header', () => { + const result = parseSkillMd(sampleSkillMd); + expect(result.apiBase).toBe('https://api.agentic.scope3.com/api/v2'); + }); + }); + + describe('command parsing', () => { + it('should parse REST commands from tables', () => { + const result = parseSkillMd(sampleSkillMd); + const restCommands = result.commands.filter((c) => c.method); + expect(restCommands.length).toBeGreaterThan(0); + }); + + it('should extract method from command', () => { + const result = parseSkillMd(sampleSkillMd); + const listCommand = result.commands.find( + (c) => c.path === '/advertisers' && c.method === 'GET' + ); + expect(listCommand).toBeDefined(); + expect(listCommand?.description).toBe('List all advertisers'); + }); + + it('should parse MCP tools', () => { + const result = parseSkillMd(sampleSkillMd); + const mcpCommands = result.commands.filter((c) => c.mcpTool); + expect(mcpCommands.length).toBeGreaterThan(0); + }); + + it('should extract parameters from endpoint path', () => { + const result = parseSkillMd(sampleSkillMd); + const getCommand = result.commands.find((c) => c.path === '/advertisers/{id}'); + expect(getCommand).toBeDefined(); + expect(getCommand?.parameters).toContainEqual( + expect.objectContaining({ name: 'id', required: true }) + ); + }); + }); + + describe('example parsing', () => { + it('should parse code examples', () => { + const result = parseSkillMd(sampleSkillMd); + expect(result.examples.length).toBeGreaterThan(0); + }); + + it('should extract language from code block', () => { + const result = parseSkillMd(sampleSkillMd); + const bashExample = result.examples.find((e) => e.language === 'bash'); + expect(bashExample).toBeDefined(); + }); + }); + + describe('edge cases', () => { + it('should handle empty content', () => { + const result = parseSkillMd(''); + expect(result.name).toBe(''); + expect(result.commands).toEqual([]); + }); + + it('should handle content without yaml header', () => { + const result = parseSkillMd('# Just a heading\n\nSome text'); + expect(result.name).toBe(''); + }); + + it('should handle content without tables', () => { + const result = parseSkillMd('```yaml\nname: test\n```\n\nNo tables here'); + expect(result.name).toBe('test'); + expect(result.commands).toEqual([]); + }); + }); +}); diff --git a/src/adapters/base.ts b/src/adapters/base.ts new file mode 100644 index 0000000..a6d24c1 --- /dev/null +++ b/src/adapters/base.ts @@ -0,0 +1,151 @@ +/** + * Base adapter interface for Scope3 API communication + */ + +import type { ApiVersion, Persona, Scope3ClientConfig } from '../types'; + +/** + * HTTP methods supported by the adapter + */ +export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; + +/** + * Request options for adapter calls + */ +export interface RequestOptions { + /** Query parameters */ + params?: Record; + /** Request timeout override */ + timeout?: number; +} + +/** + * Base adapter interface that all adapters must implement + */ +export interface BaseAdapter { + /** Base URL for API requests */ + readonly baseUrl: string; + /** API version being used */ + readonly version: ApiVersion; + /** API persona being used */ + readonly persona: Persona; + /** Whether debug mode is enabled */ + readonly debug: boolean; + + /** + * Make an API request + * @param method HTTP method + * @param path API path (without base URL, version, or persona prefix) + * @param body Request body (for POST/PUT/PATCH/DELETE) + * @param options Additional request options + */ + request( + method: HttpMethod, + path: string, + body?: unknown, + options?: RequestOptions + ): Promise; + + /** + * Connect to the API (for adapters that require connection setup) + */ + connect(): Promise; + + /** + * Disconnect from the API (for adapters that require cleanup) + */ + disconnect(): Promise; +} + +/** + * Get the default base URL for an environment + */ +export function getDefaultBaseUrl(environment: 'production' | 'staging' = 'production'): string { + return environment === 'staging' + ? 'https://api.agentic.staging.scope3.com' + : 'https://api.agentic.scope3.com'; +} + +/** + * Resolve the base URL from config + */ +export function resolveBaseUrl(config: Scope3ClientConfig): string { + if (config.baseUrl) { + return config.baseUrl.replace(/\/$/, ''); // Remove trailing slash + } + return getDefaultBaseUrl(config.environment); +} + +/** + * Resolve the API version from config + */ +export function resolveVersion(config: Scope3ClientConfig): ApiVersion { + return config.version ?? 'v2'; +} + +/** + * Resolve the persona from config + */ +export function resolvePersona(config: Scope3ClientConfig): Persona { + return config.persona; +} + +/** + * Validate and encode a resource ID for use in URL paths + * Prevents path traversal and URL injection + */ +export function validateResourceId(id: string): string { + if (!id || typeof id !== 'string') { + throw new Scope3ApiError(400, 'Resource ID is required'); + } + if (id.includes('/') || id.includes('\\') || id.includes('?') || id.includes('#')) { + throw new Scope3ApiError(400, 'Invalid resource ID format'); + } + return encodeURIComponent(id); +} + +/** + * Custom error class for Scope3 API errors + */ +export class Scope3ApiError extends Error { + constructor( + public readonly status: number, + message: string, + public readonly details?: Record + ) { + super(message); + this.name = 'Scope3ApiError'; + } +} + +/** + * Sanitize data for logging (remove sensitive fields) + */ +export function sanitizeForLogging(obj: unknown, depth = 0): unknown { + if (depth > 10 || obj === null || obj === undefined) { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map((item) => sanitizeForLogging(item, depth + 1)); + } + + if (typeof obj === 'object') { + const sanitized: Record = {}; + const sensitiveKeys = ['apiKey', 'api_key', 'token', 'password', 'secret', 'authorization']; + + for (const [key, value] of Object.entries(obj as Record)) { + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { + continue; + } + if (sensitiveKeys.some((k) => key.toLowerCase().includes(k))) { + sanitized[key] = '[REDACTED]'; + } else { + sanitized[key] = sanitizeForLogging(value, depth + 1); + } + } + return sanitized; + } + + return obj; +} diff --git a/src/adapters/index.ts b/src/adapters/index.ts new file mode 100644 index 0000000..fafcb04 --- /dev/null +++ b/src/adapters/index.ts @@ -0,0 +1,7 @@ +/** + * Adapters for Scope3 API communication + */ + +export * from './base'; +export { RestAdapter } from './rest'; +export { McpAdapter } from './mcp'; diff --git a/src/adapters/mcp.ts b/src/adapters/mcp.ts new file mode 100644 index 0000000..455158f --- /dev/null +++ b/src/adapters/mcp.ts @@ -0,0 +1,237 @@ +/** + * MCP (Model Context Protocol) adapter for Scope3 API + * Primary adapter for AI agents (Claude, etc.) + */ + +import { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; +import type { ApiVersion, Persona, Scope3ClientConfig } from '../types'; +import { + BaseAdapter, + HttpMethod, + RequestOptions, + Scope3ApiError, + resolveBaseUrl, + resolveVersion, + resolvePersona, + sanitizeForLogging, +} from './base'; +import { logger } from '../utils/logger'; + +const SDK_VERSION = '2.0.0'; + +/** + * MCP adapter implementation using Model Context Protocol + * Uses the single `api_call` tool to make REST-style requests + */ +export class McpAdapter implements BaseAdapter { + readonly baseUrl: string; + readonly version: ApiVersion; + readonly persona: Persona; + readonly debug: boolean; + + private readonly apiKey: string; + private mcpClient: Client; + private transport: StreamableHTTPClientTransport; + private connected = false; + private connectPromise: Promise | null = null; + + constructor(config: Scope3ClientConfig) { + this.apiKey = config.apiKey; + this.baseUrl = resolveBaseUrl(config); + this.version = resolveVersion(config); + this.persona = resolvePersona(config); + this.debug = config.debug ?? false; + + // Initialize MCP client + this.mcpClient = new Client( + { + name: 'scope3-sdk', + version: SDK_VERSION, + }, + { + capabilities: { + tools: {}, + }, + } + ); + + // Initialize transport + this.transport = new StreamableHTTPClientTransport(new URL(`${this.baseUrl}/mcp`), { + requestInit: { + headers: { + Authorization: `Bearer ${this.apiKey}`, + }, + }, + }); + + if (this.debug) { + logger.setDebug(true); + logger.debug('McpAdapter initialized', { + baseUrl: this.baseUrl, + version: this.version, + persona: this.persona, + }); + } + } + + /** + * Connect to MCP server + */ + async connect(): Promise { + if (this.connected) { + return; + } + if (!this.connectPromise) { + this.connectPromise = this.doConnect(); + } + return this.connectPromise; + } + + private async doConnect(): Promise { + try { + await this.mcpClient.connect(this.transport); + this.connected = true; + + if (this.debug) { + logger.debug('MCP connected'); + } + } catch (error) { + this.connectPromise = null; // Allow retry on failure + throw new Scope3ApiError( + 0, + `Failed to connect to MCP server: ${error instanceof Error ? error.message : 'Unknown error'}` + ); + } + } + + /** + * Disconnect from MCP server + */ + async disconnect(): Promise { + if (!this.connected) { + return; + } + + try { + await this.mcpClient.close(); + await this.transport.close(); + this.connected = false; + + if (this.debug) { + logger.debug('MCP disconnected'); + } + } catch (error) { + logger.error('Error disconnecting from MCP', error); + } + } + + /** + * Make an API request via MCP using the api_call tool + */ + async request( + method: HttpMethod, + path: string, + body?: unknown, + options?: RequestOptions + ): Promise { + // Ensure connected + if (!this.connected) { + await this.connect(); + } + + const startTime = Date.now(); + + // Build full API path with version and persona + const versionPath = this.version === 'latest' ? 'v2' : this.version; + let fullPath = `/api/${versionPath}/${this.persona}${path}`; + + // Add query parameters to path + if (options?.params) { + const params = new URLSearchParams(); + for (const [key, value] of Object.entries(options.params)) { + if (value !== undefined) { + params.append(key, String(value)); + } + } + const queryString = params.toString(); + if (queryString) { + fullPath += `?${queryString}`; + } + } + + // Build MCP tool arguments for api_call + const args: Record = { + method, + path: fullPath, + ...(body && typeof body === 'object' ? { body } : {}), + }; + + if (this.debug) { + logger.debug('MCP Request', { + tool: 'api_call', + args: sanitizeForLogging(args), + }); + } + + try { + const result = await this.mcpClient.callTool({ + name: 'api_call', + arguments: args, + }); + + // Check for MCP-level errors + if (result.isError) { + const errorContent = result.content as Array<{ type: string; text?: string }> | undefined; + const errorMessage = errorContent?.[0]?.text ?? 'MCP tool call failed'; + try { + const parsed = JSON.parse(errorMessage); + throw new Scope3ApiError( + parsed.status ?? parsed.code ?? 500, + parsed.message ?? errorMessage, + parsed.details + ); + } catch (e) { + if (e instanceof Scope3ApiError) throw e; + throw new Scope3ApiError(500, errorMessage); + } + } + + const durationMs = Date.now() - startTime; + + if (this.debug) { + logger.debug('MCP Response', { + durationMs, + hasStructuredContent: !!result.structuredContent, + }); + } + + // Extract structured content + if (result.structuredContent) { + return result.structuredContent as T; + } + + // Fall back to text content if no structured content + const content = result.content as Array<{ type: string; text?: string }> | undefined; + if (content && content.length > 0 && content[0].type === 'text' && content[0].text) { + try { + return JSON.parse(content[0].text) as T; + } catch { + // Return as message + return { message: content[0].text } as T; + } + } + + throw new Scope3ApiError(500, 'MCP returned no content'); + } catch (error) { + if (error instanceof Scope3ApiError) { + throw error; + } + + throw new Scope3ApiError( + 500, + `MCP error: ${error instanceof Error ? error.message : 'Unknown error'}` + ); + } + } +} diff --git a/src/adapters/rest.ts b/src/adapters/rest.ts new file mode 100644 index 0000000..f9f4695 --- /dev/null +++ b/src/adapters/rest.ts @@ -0,0 +1,181 @@ +/** + * REST adapter for Scope3 API + * Primary adapter for human developers and CLI + */ + +import type { ApiVersion, Persona, Scope3ClientConfig } from '../types'; +import { + BaseAdapter, + HttpMethod, + RequestOptions, + Scope3ApiError, + resolveBaseUrl, + resolveVersion, + resolvePersona, + sanitizeForLogging, +} from './base'; +import { logger } from '../utils/logger'; + +/** + * REST adapter implementation using native fetch + */ +export class RestAdapter implements BaseAdapter { + readonly baseUrl: string; + readonly version: ApiVersion; + readonly persona: Persona; + readonly debug: boolean; + + private readonly apiKey: string; + private readonly timeout: number; + + constructor(config: Scope3ClientConfig) { + this.apiKey = config.apiKey; + this.baseUrl = resolveBaseUrl(config); + this.version = resolveVersion(config); + this.persona = resolvePersona(config); + this.debug = config.debug ?? false; + this.timeout = config.timeout ?? 30000; + + if (this.debug) { + logger.setDebug(true); + logger.debug('RestAdapter initialized', { + baseUrl: this.baseUrl, + version: this.version, + persona: this.persona, + }); + } + } + + /** + * Make an HTTP request to the Scope3 API + */ + async request( + method: HttpMethod, + path: string, + body?: unknown, + options?: RequestOptions + ): Promise { + const startTime = Date.now(); + + // Build URL with version and persona prefix + const versionPath = this.version === 'latest' ? 'v2' : this.version; + let url = `${this.baseUrl}/api/${versionPath}/${this.persona}${path}`; + + // Add query parameters + if (options?.params) { + const params = new URLSearchParams(); + for (const [key, value] of Object.entries(options.params)) { + if (value !== undefined) { + params.append(key, String(value)); + } + } + const queryString = params.toString(); + if (queryString) { + url += `?${queryString}`; + } + } + + // Build request options + const fetchOptions: RequestInit = { + method, + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${this.apiKey}`, + }, + signal: AbortSignal.timeout(options?.timeout ?? this.timeout), + }; + + if ( + body && + (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'DELETE') + ) { + fetchOptions.body = JSON.stringify(body); + } + + if (this.debug) { + logger.debug('REST Request', { + method, + url, + body: body ? sanitizeForLogging(body) : undefined, + }); + } + + try { + const response = await fetch(url, fetchOptions); + const durationMs = Date.now() - startTime; + + // Handle 204 No Content + if (response.status === 204) { + if (this.debug) { + logger.debug('REST Response', { status: 204, durationMs }); + } + return undefined as T; + } + + // Handle non-JSON responses + const contentType = response.headers.get('content-type'); + let data: unknown; + + if (contentType?.includes('application/json')) { + data = await response.json(); + } else { + const text = await response.text(); + data = text ? { message: text } : {}; + } + + if (this.debug) { + logger.debug('REST Response', { + status: response.status, + durationMs, + data: sanitizeForLogging(data), + }); + } + + // Handle error responses + if (!response.ok) { + // Extract error from API envelope: { error: { code, message, details } } + const envelope = data as Record; + const apiError = envelope?.error as Record | undefined; + + const errorMessage = + (apiError?.message as string) ?? + (envelope?.message as string) ?? + `HTTP ${response.status}`; + + const details = (apiError?.details as Record) ?? undefined; + + throw new Scope3ApiError(response.status, errorMessage, details); + } + + return data as T; + } catch (error) { + if (error instanceof Scope3ApiError) { + throw error; + } + + // Handle fetch errors (network, timeout, etc.) + if (error instanceof Error) { + if (error.name === 'AbortError' || error.name === 'TimeoutError') { + throw new Scope3ApiError(408, `Request timeout after ${this.timeout}ms`); + } + throw new Scope3ApiError(0, `Network error: ${error.message}`); + } + + throw new Scope3ApiError(0, 'Unknown error occurred'); + } + } + + /** + * REST adapter doesn't need explicit connection + */ + async connect(): Promise { + // No-op for REST adapter + } + + /** + * REST adapter doesn't need explicit disconnection + */ + async disconnect(): Promise { + // No-op for REST adapter + } +} diff --git a/src/cli.ts b/src/cli.ts deleted file mode 100644 index 36b82a8..0000000 --- a/src/cli.ts +++ /dev/null @@ -1,772 +0,0 @@ -#!/usr/bin/env node - -import { Command } from 'commander'; -import { PlatformClient } from './platform-client'; -import Table from 'cli-table3'; -import chalk from 'chalk'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as os from 'os'; -import { logger } from './utils/logger'; - -// Configuration file location -const CONFIG_DIR = path.join(os.homedir(), '.scope3'); -const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json'); -const TOOLS_CACHE_FILE = path.join(CONFIG_DIR, 'tools-cache.json'); -const CACHE_TTL = 24 * 60 * 60 * 1000; // 24 hours - -interface CliConfig { - apiKey?: string; // Legacy single API key - productionApiKey?: string; // Production-specific API key - stagingApiKey?: string; // Staging-specific API key - environment?: 'production' | 'staging'; - baseUrl?: string; -} - -interface ToolsCache { - tools: McpTool[]; - timestamp: number; -} - -interface McpTool { - name: string; - description?: string; - inputSchema: { - type: string; - properties?: Record; - required?: string[]; - }; -} - -// Load config from file or environment -function loadConfig(): CliConfig { - const config: CliConfig = {}; - - // Try to load from config file - if (fs.existsSync(CONFIG_FILE)) { - try { - const fileConfig = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8')); - config.apiKey = fileConfig.apiKey; - config.productionApiKey = fileConfig.productionApiKey; - config.stagingApiKey = fileConfig.stagingApiKey; - config.environment = fileConfig.environment; - config.baseUrl = fileConfig.baseUrl; - } catch (error) { - logger.warn('Failed to parse config file', { error }); - console.error(chalk.yellow('Warning: Failed to parse config file')); - } - } - - // Environment variables override config file - if (process.env.SCOPE3_API_KEY) { - config.apiKey = process.env.SCOPE3_API_KEY; - } - if (process.env.SCOPE3_ENVIRONMENT) { - const env = process.env.SCOPE3_ENVIRONMENT.toLowerCase(); - if (env === 'production' || env === 'staging') { - config.environment = env; - } else { - console.warn( - chalk.yellow( - `Warning: Invalid SCOPE3_ENVIRONMENT value "${process.env.SCOPE3_ENVIRONMENT}". ` + - 'Valid values: production, staging. Using default (production).' - ) - ); - } - } - if (process.env.SCOPE3_BASE_URL) { - config.baseUrl = process.env.SCOPE3_BASE_URL; - } - - return config; -} - -// Save config to file -function saveConfig(config: CliConfig): void { - if (!fs.existsSync(CONFIG_DIR)) { - fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 }); // Owner-only directory - } - - // Write config with restricted permissions (owner read/write only) - fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 }); - - console.log(chalk.green(`โœ“ Configuration saved to ${CONFIG_FILE}`)); - - // Warn about plain-text storage if API key is being saved - if (config.apiKey) { - console.log(chalk.yellow('\nโš  Security Notice:')); - console.log( - chalk.gray(' API key stored in plain text with file permissions 0600 (owner only)') - ); - console.log(chalk.gray(' For better security, consider using environment variables:')); - console.log(chalk.gray(' export SCOPE3_API_KEY=your_key')); - } -} - -// Load tools cache -function loadToolsCache(): ToolsCache | null { - if (!fs.existsSync(TOOLS_CACHE_FILE)) { - return null; - } - - try { - const cache: ToolsCache = JSON.parse(fs.readFileSync(TOOLS_CACHE_FILE, 'utf-8')); - const age = Date.now() - cache.timestamp; - - if (age > CACHE_TTL) { - return null; // Cache expired - } - - return cache; - } catch (error) { - return null; - } -} - -// Save tools cache -function saveToolsCache(tools: McpTool[]): void { - if (!fs.existsSync(CONFIG_DIR)) { - fs.mkdirSync(CONFIG_DIR, { recursive: true }); - } - - const cache: ToolsCache = { - tools, - timestamp: Date.now(), - }; - - fs.writeFileSync(TOOLS_CACHE_FILE, JSON.stringify(cache, null, 2)); -} - -// Fetch available tools from MCP server -async function fetchAvailableTools(client: PlatformClient, useCache = true): Promise { - // Try cache first - if (useCache) { - const cache = loadToolsCache(); - if (cache) { - return cache.tools; - } - } - - // Fetch from server - try { - await client.connect(); - const response = (await client.listTools()) as { tools: McpTool[] }; - const tools = response.tools; - - // Save to cache - saveToolsCache(tools); - - return tools; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - logger.error('Error fetching tools', error); - console.error(chalk.red('Error fetching tools:'), errorMessage); - - // Try to use stale cache as fallback - if (fs.existsSync(TOOLS_CACHE_FILE)) { - try { - console.log(chalk.yellow('Using cached tools (may be outdated)')); - const cache: ToolsCache = JSON.parse(fs.readFileSync(TOOLS_CACHE_FILE, 'utf-8')); - return cache.tools; - } catch (cacheError) { - logger.warn('Failed to read stale cache', { error: cacheError }); - // Fall through to throw original error since we can't recover - } - } - - throw error; - } -} - -// Format output based on format option -function formatOutput(data: unknown, format: string): void { - if (format === 'json') { - console.log(JSON.stringify(data, null, 2)); - return; - } - - if (!data) { - console.log(chalk.yellow('No data to display')); - return; - } - - // Handle ToolResponse wrapper - const dataObj = data as Record; - let actualData: unknown = dataObj.data || data; - - // Extract and display human-readable message if present (from MCP content.text) - let humanMessage: string | undefined; - if (typeof actualData === 'object' && actualData && '_message' in actualData) { - const dataRecord = actualData as Record; - humanMessage = String(dataRecord._message); - // Remove _message from the data to process - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { _message, ...rest } = dataRecord; - actualData = rest; - } - - // Display the human-readable message first (if not in JSON mode) - if (humanMessage) { - console.log(chalk.cyan(humanMessage)); - console.log(); // Blank line before structured data - } - - // If the response has an array field, extract it (common pattern for list responses) - // Check for: items, brandAgents, campaigns, agents, etc. - if (typeof actualData === 'object' && actualData && !Array.isArray(actualData)) { - const dataRecord = actualData as Record; - // Find the first array field (including empty arrays) - const arrayField = Object.keys(dataRecord).find((key) => Array.isArray(dataRecord[key])); - if (arrayField) { - actualData = dataRecord[arrayField]; - } - } - - // If the response is just a single object with only a "message" field, - // display the message directly without table formatting - if ( - typeof actualData === 'object' && - actualData && - !Array.isArray(actualData) && - Object.keys(actualData).length === 1 && - 'message' in actualData - ) { - console.log(String((actualData as Record).message)); - return; - } - - // Helper function to intelligently display or summarize values - function summarizeValue(value: unknown): string { - if (value === null || value === undefined) { - return chalk.gray('(empty)'); - } - - // Handle arrays - if (Array.isArray(value)) { - if (value.length === 0) return chalk.gray('(empty array)'); - - // Small arrays of primitives: show inline - if (value.length <= 3 && value.every((item) => typeof item !== 'object' || item === null)) { - const str = JSON.stringify(value); - if (str.length <= 50) return str; - } - - // Large or complex arrays: summarize - return chalk.gray(`(${value.length} item${value.length === 1 ? '' : 's'})`); - } - - // Handle objects - if (typeof value === 'object') { - const obj = value as Record; - const keys = Object.keys(obj); - if (keys.length === 0) return chalk.gray('(empty object)'); - - // Simple objects with 1-2 primitive fields: show inline - if (keys.length <= 2) { - const allPrimitive = keys.every((k) => { - const v = obj[k]; - return typeof v !== 'object' || v === null; - }); - - if (allPrimitive) { - const str = JSON.stringify(value); - if (str.length <= 50) return str; - } - } - - // Complex objects: summarize - return chalk.gray(`(${keys.length} field${keys.length === 1 ? '' : 's'})`); - } - - return String(value); - } - - if (Array.isArray(actualData)) { - if (actualData.length === 0) { - console.log(chalk.yellow('No results found')); - return; - } - - if (format === 'list') { - // List format: show each item with summaries for arrays/objects - actualData.forEach((item, index) => { - console.log(chalk.cyan(`\n${index + 1}.`)); - Object.entries(item).forEach(([key, value]) => { - const displayValue = summarizeValue(value); - console.log(` ${chalk.yellow(key)}: ${displayValue}`); - }); - }); - console.log(); // Extra line at end - } else { - // Table format: columnar view with summaries - const keys = Object.keys(actualData[0]); - const table = new Table({ - head: keys.map((k) => chalk.cyan(k)), - wordWrap: true, - wrapOnWordBoundary: false, - }); - - actualData.forEach((item) => { - table.push( - keys.map((k) => { - const value = item[k]; - if (value === null || value === undefined) return ''; - - // Use intelligent summarization for table cells too - if (Array.isArray(value)) { - if (value.length === 0) return ''; - // Small primitive arrays: show inline - if ( - value.length <= 3 && - value.every((item) => typeof item !== 'object' || item === null) - ) { - const str = JSON.stringify(value); - if (str.length <= 50) return str; - } - return `${value.length} item${value.length === 1 ? '' : 's'}`; - } - - if (typeof value === 'object') { - const obj = value as Record; - const objKeys = Object.keys(obj); - if (objKeys.length === 0) return ''; - // Simple objects: show inline - if (objKeys.length <= 2) { - const allPrimitive = objKeys.every((k) => { - const v = obj[k]; - return typeof v !== 'object' || v === null; - }); - if (allPrimitive) { - const str = JSON.stringify(value); - if (str.length <= 50) return str; - } - } - return `${objKeys.length} field${objKeys.length === 1 ? '' : 's'}`; - } - - return String(value); - }) - ); - }); - - console.log(table.toString()); - } - } else if (typeof actualData === 'object' && actualData) { - // Create table for single object with summaries - const table = new Table({ - wordWrap: true, - wrapOnWordBoundary: false, - }); - - Object.entries(actualData as Record).forEach(([key, value]) => { - const displayValue = summarizeValue(value); - table.push({ [chalk.cyan(key)]: displayValue }); - }); - - console.log(table.toString()); - } else { - console.log(actualData); - } - - // Show success indicator if present (but don't duplicate message display) - if (dataObj.success !== undefined) { - console.log(dataObj.success ? chalk.green('โœ“ Success') : chalk.red('โœ— Failed')); - } -} - -// Create client instance -function createClient( - apiKey?: string, - environment?: 'production' | 'staging', - baseUrl?: string, - debug?: boolean -): PlatformClient { - const config = loadConfig(); - - // Determine final environment - const finalEnvironment = environment || config.environment || 'production'; - - // Select API key based on priority: - // 1. Explicitly passed apiKey (--api-key flag) - // 2. Environment-specific key from config (productionApiKey/stagingApiKey) - // 3. Legacy single apiKey from config - let finalApiKey = apiKey; - if (!finalApiKey) { - if (finalEnvironment === 'staging' && config.stagingApiKey) { - finalApiKey = config.stagingApiKey; - } else if (finalEnvironment === 'production' && config.productionApiKey) { - finalApiKey = config.productionApiKey; - } else { - finalApiKey = config.apiKey; // Fallback to legacy key - } - } - - if (!finalApiKey) { - console.error(chalk.red('Error: API key is required')); - console.log('Set it via:'); - console.log(' - Environment variable: export SCOPE3_API_KEY=your_key'); - console.log(' - Config command: scope3 config set apiKey your_key'); - console.log(' - Or use environment-specific keys:'); - console.log(' scope3 config set productionApiKey your_production_key'); - console.log(' scope3 config set stagingApiKey your_staging_key'); - console.log(' - Flag: --api-key your_key'); - process.exit(1); - } - - return new PlatformClient({ - apiKey: finalApiKey, - environment: finalEnvironment, - baseUrl: baseUrl || config.baseUrl, - debug: debug || false, - }); -} - -// Parse parameter value based on schema type -function parseParameterValue(value: string, schema: Record): unknown { - const type = schema.type as string; - - if (type === 'object' || type === 'array') { - try { - return JSON.parse(value); - } catch (error) { - logger.error('Invalid JSON parameter', error, { value, type }); - console.error(chalk.red(`Error: Invalid JSON for parameter: ${value}`)); - process.exit(1); - } - } - - if (type === 'integer' || type === 'number') { - const num = Number(value); - if (isNaN(num)) { - logger.error('Invalid number parameter', undefined, { value, type }); - console.error(chalk.red(`Error: Invalid number: ${value}`)); - process.exit(1); - } - return num; - } - - if (type === 'boolean') { - if (value === 'true') return true; - if (value === 'false') return false; - logger.error('Invalid boolean parameter', undefined, { value, type }); - console.error(chalk.red(`Error: Invalid boolean (use 'true' or 'false'): ${value}`)); - process.exit(1); - } - - // Default to string - return value; -} - -// Parse tool name into resource and method -function parseToolName(toolName: string): { resource: string; method: string } { - const parts = toolName.split('_'); - - if (parts.length < 2) { - return { resource: 'tools', method: toolName }; - } - - // Handle cases like "campaigns_create", "brand_agents_list", etc. - const method = parts[parts.length - 1]; - const resource = parts.slice(0, -1).join('-'); - - return { resource, method }; -} - -// Main program -const program = new Command(); - -program - .name('scope3') - .description('CLI tool for Scope3 Agentic API (dynamically generated from MCP server)') - .version('1.0.0') - .option('--api-key ', 'API key for authentication') - .option( - '--environment ', - 'Environment: production or staging (default: production)', - 'production' - ) - .option('--base-url ', 'Base URL for API (overrides environment)') - .option('--format ', 'Output format: json, table, or list (default: table)', 'table') - .option('--debug', 'Enable debug mode (show request/response details)') - .option('--no-cache', 'Skip cache and fetch fresh tools list'); - -// Config command -const configCmd = program.command('config').description('Manage CLI configuration'); - -configCmd - .command('set') - .description('Set configuration value') - .argument( - '', - 'Configuration key (apiKey, productionApiKey, stagingApiKey, environment, or baseUrl)' - ) - .argument('', 'Configuration value') - .action((key: string, value: string) => { - const config = loadConfig(); - if (key === 'apiKey') { - config.apiKey = value; - } else if (key === 'productionApiKey') { - config.productionApiKey = value; - } else if (key === 'stagingApiKey') { - config.stagingApiKey = value; - } else if (key === 'environment') { - if (value !== 'production' && value !== 'staging') { - console.error(chalk.red(`Error: Invalid environment: ${value}`)); - console.log('Valid values: production, staging'); - process.exit(1); - } - config.environment = value as 'production' | 'staging'; - } else if (key === 'baseUrl') { - config.baseUrl = value; - } else { - console.error(chalk.red(`Error: Unknown config key: ${key}`)); - console.log('Valid keys: apiKey, productionApiKey, stagingApiKey, environment, baseUrl'); - process.exit(1); - } - saveConfig(config); - }); - -configCmd - .command('get') - .description('Get configuration value') - .argument( - '[key]', - 'Configuration key (apiKey, productionApiKey, stagingApiKey, environment, or baseUrl). If omitted, shows all config' - ) - .action((key?: string) => { - const config = loadConfig(); - if (!key) { - // Redact sensitive values when displaying full config - const safeConfig = { ...config }; - if (safeConfig.apiKey) { - safeConfig.apiKey = safeConfig.apiKey.substring(0, 8) + '...[REDACTED]'; - } - if (safeConfig.productionApiKey) { - safeConfig.productionApiKey = safeConfig.productionApiKey.substring(0, 8) + '...[REDACTED]'; - } - if (safeConfig.stagingApiKey) { - safeConfig.stagingApiKey = safeConfig.stagingApiKey.substring(0, 8) + '...[REDACTED]'; - } - console.log(JSON.stringify(safeConfig, null, 2)); - } else if (key in config) { - console.log(config[key as keyof CliConfig]); - } else { - console.error(chalk.red(`Error: Unknown config key: ${key}`)); - process.exit(1); - } - }); - -configCmd - .command('clear') - .description('Clear all configuration') - .action(() => { - if (fs.existsSync(CONFIG_FILE)) { - fs.unlinkSync(CONFIG_FILE); - console.log(chalk.green('Configuration cleared')); - } else { - console.log(chalk.yellow('No configuration file found')); - } - }); - -// List available tools command -program - .command('list-tools') - .description('List all available API tools') - .option('--refresh', 'Refresh tools cache') - .action(async (options) => { - const globalOpts = program.opts(); - const client = createClient( - globalOpts.apiKey, - globalOpts.environment, - globalOpts.baseUrl, - globalOpts.debug - ); - - try { - const useCache = !options.refresh && globalOpts.cache !== false; - const tools = await fetchAvailableTools(client, useCache); - - console.log(chalk.green(`\nFound ${tools.length} available tools:\n`)); - - // Group by resource - const grouped: Record = {}; - tools.forEach((tool) => { - const { resource } = parseToolName(tool.name); - if (!grouped[resource]) { - grouped[resource] = []; - } - grouped[resource].push(tool); - }); - - // Display grouped - Object.entries(grouped) - .sort() - .forEach(([resource, resourceTools]) => { - console.log(chalk.cyan.bold(`\n${resource}:`)); - resourceTools.forEach((tool) => { - const { method } = parseToolName(tool.name); - const desc = tool.description || 'No description'; - console.log(` ${chalk.yellow(method)} - ${desc}`); - }); - }); - - console.log(); - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - console.error(chalk.red('Error:'), errorMessage); - process.exit(1); - } finally { - await client.disconnect(); - } - }); - -// Dynamic command generation -async function setupDynamicCommands() { - const globalOpts = program.opts(); - - // For help/version/config commands, don't fetch tools - const args = process.argv.slice(2); - if ( - args.length === 0 || - args.includes('--help') || - args.includes('-h') || - args.includes('--version') || - args.includes('-V') || - args[0] === 'config' || - args[0] === 'list-tools' - ) { - return; - } - - try { - const client = createClient( - globalOpts.apiKey, - globalOpts.environment, - globalOpts.baseUrl, - globalOpts.debug - ); - const useCache = globalOpts.cache !== false; - const tools = await fetchAvailableTools(client, useCache); - await client.disconnect(); - - // Group tools by resource - const resourceGroups: Record = {}; - tools.forEach((tool) => { - const { resource } = parseToolName(tool.name); - if (!resourceGroups[resource]) { - resourceGroups[resource] = []; - } - resourceGroups[resource].push(tool); - }); - - // Create commands for each resource - Object.entries(resourceGroups).forEach(([resourceName, resourceTools]) => { - const resourceCmd = program - .command(resourceName) - .description(`Manage ${resourceName} (${resourceTools.length} operations)`); - - resourceTools.forEach((tool) => { - const { method } = parseToolName(tool.name); - const cmd = resourceCmd - .command(method) - .description(tool.description || `${method} operation`); - - // Add options from schema - const properties = (tool.inputSchema.properties || {}) as Record< - string, - Record - >; - const required = tool.inputSchema.required || []; - - Object.entries(properties).forEach(([paramName, paramSchema]) => { - const isRequired = required.includes(paramName); - const paramType = paramSchema.type as string; - const paramDesc = (paramSchema.description as string) || paramName; - - const flag = `--${paramName} `; - const description = `${paramDesc}${isRequired ? ' (required)' : ' (optional)'} [${paramType}]`; - - cmd.option(flag, description); - }); - - // Action handler - cmd.action(async (options) => { - const client = createClient( - globalOpts.apiKey, - globalOpts.environment, - globalOpts.baseUrl, - globalOpts.debug - ); - - try { - await client.connect(); - - // Build request from options - const request: Record = {}; - Object.entries(properties).forEach(([paramName, paramSchema]) => { - const value = options[paramName]; - if (value !== undefined) { - request[paramName] = parseParameterValue( - value, - paramSchema as Record - ); - } - }); - - // Validate required params - const missing = required.filter((p) => request[p] === undefined); - if (missing.length > 0) { - console.error(chalk.red(`Error: Missing required parameters: ${missing.join(', ')}`)); - process.exit(1); - } - - // Call the tool - const result = await client.callTool(tool.name, request); - formatOutput(result, globalOpts.format); - } catch (error: unknown) { - const errorMessage = error instanceof Error ? error.message : String(error); - const errorStack = error instanceof Error ? error.stack : undefined; - - // Only log to logger in debug mode - if (globalOpts.debug) { - logger.error('Tool execution failed', error, { toolName: tool.name }); - } - - console.error(chalk.red('Error:'), errorMessage); - - // Show stack trace only in debug mode - if (errorStack && globalOpts.debug) { - console.error(chalk.gray('\nStack trace:')); - console.error(chalk.gray(errorStack)); - } - process.exit(1); - } finally { - await client.disconnect(); - } - }); - }); - }); - } catch (error) { - // If we can't fetch tools, show a helpful error - const errorMessage = error instanceof Error ? error.message : String(error); - logger.error('CLI initialization failed', error); - console.error(chalk.red('Error initializing CLI:'), errorMessage); - console.log(chalk.yellow('\nMake sure your API key is configured:')); - console.log(' scope3 config set apiKey YOUR_KEY'); - console.log('\nOr set via environment:'); - console.log(' export SCOPE3_API_KEY=YOUR_KEY'); - process.exit(1); - } -} - -// Setup and parse -setupDynamicCommands() - .then(() => { - program.parse(); - }) - .catch((error) => { - const errorMessage = error instanceof Error ? error.message : String(error); - logger.error('Fatal CLI error', error); - console.error(chalk.red('Fatal error:'), errorMessage); - process.exit(1); - }); diff --git a/src/cli/commands/advertisers.ts b/src/cli/commands/advertisers.ts new file mode 100644 index 0000000..5420c0e --- /dev/null +++ b/src/cli/commands/advertisers.ts @@ -0,0 +1,131 @@ +/** + * Advertiser commands + */ + +import { Command } from 'commander'; +import { createClient, GlobalOptions } from '../utils'; +import { formatOutput, printError, printSuccess, OutputFormat } from '../format'; + +export const advertisersCommand = new Command('advertisers').description('Manage advertisers'); + +/** + * List advertisers + */ +advertisersCommand + .command('list') + .description('List all advertisers') + .option('--take ', 'Maximum number of results', '50') + .option('--skip ', 'Number of results to skip', '0') + .option('--status ', 'Filter by status (ACTIVE, ARCHIVED)') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.advertisers.list({ + take: parseInt(options.take, 10), + skip: parseInt(options.skip, 10), + status: options.status, + }); + + formatOutput(result, globalOpts.format as OutputFormat); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Get advertiser by ID + */ +advertisersCommand + .command('get ') + .description('Get advertiser by ID') + .action(async (id: string, options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.advertisers.get(id); + formatOutput(result, globalOpts.format as OutputFormat); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Create advertiser + */ +advertisersCommand + .command('create') + .description('Create a new advertiser') + .requiredOption('--name ', 'Advertiser name') + .option('--description ', 'Advertiser description') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.advertisers.create({ + name: options.name, + description: options.description, + }); + + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess(`Created advertiser: ${result.data.id}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Update advertiser + */ +advertisersCommand + .command('update ') + .description('Update an advertiser') + .option('--name ', 'New name') + .option('--description ', 'New description') + .action(async (id: string, options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const updateData: { name?: string; description?: string } = {}; + if (options.name) updateData.name = options.name; + if (options.description) updateData.description = options.description; + + if (Object.keys(updateData).length === 0) { + printError('No update fields provided. Use --name or --description'); + process.exit(1); + } + + const result = await client.advertisers.update(id, updateData); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess('Advertiser updated'); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Delete advertiser + */ +advertisersCommand + .command('delete ') + .description('Delete an advertiser') + .action(async (id: string, options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + await client.advertisers.delete(id); + printSuccess(`Deleted advertiser: ${id}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); diff --git a/src/cli/commands/brands.ts b/src/cli/commands/brands.ts new file mode 100644 index 0000000..c3048f8 --- /dev/null +++ b/src/cli/commands/brands.ts @@ -0,0 +1,256 @@ +/** + * Brand commands - supports both buyer and brand persona modes + * + * Brand persona: manage brand identities directly (list, get, create, update, delete) + * Buyer persona: discover brands and manage brand-advertiser links (list, link, unlink, get-linked) + */ + +import { Command } from 'commander'; +import { createClient, GlobalOptions, parseJsonArg } from '../utils'; +import { formatOutput, printError, printSuccess, OutputFormat } from '../format'; +import type { CreateBrandInput, UpdateBrandInput, BrandManifest } from '../../types'; + +export const brandsCommand = new Command('brands').description( + 'Manage brands (behavior depends on --persona)' +); + +/** + * List brands + * - Brand persona: lists all owned brands + * - Buyer persona: lists all brands available to the buyer + */ +brandsCommand + .command('list') + .description('List brands (brand persona: owned brands, buyer persona: available brands)') + .option('--take ', 'Maximum number of results', '50') + .option('--skip ', 'Number of results to skip', '0') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + const persona = globalOpts.persona || 'buyer'; + + if (persona === 'brand') { + const result = await client.brands.list({ + take: parseInt(options.take, 10), + skip: parseInt(options.skip, 10), + }); + formatOutput(result, globalOpts.format as OutputFormat); + } else { + // Buyer persona - use buyerBrands + const result = await client.buyerBrands.list({ + take: parseInt(options.take, 10), + skip: parseInt(options.skip, 10), + }); + formatOutput(result, globalOpts.format as OutputFormat); + } + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Get a brand by ID (brand persona only) + */ +brandsCommand + .command('get ') + .description('Get brand by ID (brand persona)') + .action(async (id: string, _options: unknown, cmd: Command) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + if ((globalOpts.persona || 'buyer') !== 'brand') { + printError('The "brands get" command requires --persona brand'); + process.exit(1); + } + const client = createClient(globalOpts); + + const result = await client.brands.get(id); + formatOutput(result, globalOpts.format as OutputFormat); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Create a brand (brand persona only) + */ +brandsCommand + .command('create') + .description('Create a new brand (brand persona)') + .option('--manifest-url ', 'Brand manifest URL') + .option('--manifest-json ', 'Brand manifest as JSON string') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + if ((globalOpts.persona || 'buyer') !== 'brand') { + printError('The "brands create" command requires --persona brand'); + process.exit(1); + } + const client = createClient(globalOpts); + + const data: CreateBrandInput = {}; + + if (options.manifestUrl) { + data.manifestUrl = options.manifestUrl; + } + + if (options.manifestJson) { + const parsed = parseJsonArg(options.manifestJson); + if (typeof parsed === 'string') { + printError('Invalid JSON for --manifest-json'); + process.exit(1); + } + data.manifestJson = parsed; + } + + if (!data.manifestUrl && !data.manifestJson) { + printError('Either --manifest-url or --manifest-json is required'); + process.exit(1); + } + + const result = await client.brands.create(data); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess(`Created brand: ${result.data.id}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Update a brand (brand persona only) + */ +brandsCommand + .command('update ') + .description('Update a brand (brand persona)') + .option('--manifest-url ', 'New brand manifest URL') + .option('--manifest-json ', 'New brand manifest as JSON string') + .action(async (id: string, options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + if ((globalOpts.persona || 'buyer') !== 'brand') { + printError('The "brands update" command requires --persona brand'); + process.exit(1); + } + const client = createClient(globalOpts); + + const data: UpdateBrandInput = {}; + + if (options.manifestUrl) { + data.manifestUrl = options.manifestUrl; + } + + if (options.manifestJson) { + const parsed = parseJsonArg(options.manifestJson); + if (typeof parsed === 'string') { + printError('Invalid JSON for --manifest-json'); + process.exit(1); + } + data.manifestJson = parsed; + } + + if (!data.manifestUrl && !data.manifestJson) { + printError('Provide --manifest-url or --manifest-json to update'); + process.exit(1); + } + + const result = await client.brands.update(id, data); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess('Brand updated'); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Delete a brand (brand persona only) + */ +brandsCommand + .command('delete ') + .description('Delete a brand (brand persona)') + .action(async (id: string, _options: unknown, cmd: Command) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + if ((globalOpts.persona || 'buyer') !== 'brand') { + printError('The "brands delete" command requires --persona brand'); + process.exit(1); + } + const client = createClient(globalOpts); + + await client.brands.delete(id); + printSuccess(`Deleted brand: ${id}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +// โ”€โ”€ Buyer persona brand-advertiser linking commands โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +/** + * Link a brand to an advertiser (buyer persona) + */ +brandsCommand + .command('link') + .description('Link a brand to an advertiser (buyer persona)') + .requiredOption('--advertiser-id ', 'Advertiser ID') + .requiredOption('--brand-id ', 'Brand ID to link') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.advertisers.brand(options.advertiserId).link({ + brandId: options.brandId, + }); + + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess(`Linked brand ${options.brandId} to advertiser ${options.advertiserId}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Unlink a brand from an advertiser (buyer persona) + */ +brandsCommand + .command('unlink') + .description('Unlink the brand from an advertiser (buyer persona)') + .requiredOption('--advertiser-id ', 'Advertiser ID') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + await client.advertisers.brand(options.advertiserId).unlink(); + printSuccess(`Unlinked brand from advertiser ${options.advertiserId}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Get the brand linked to an advertiser (buyer persona) + */ +brandsCommand + .command('get-linked') + .description('Get the brand linked to an advertiser (buyer persona)') + .requiredOption('--advertiser-id ', 'Advertiser ID') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.advertisers.brand(options.advertiserId).get(); + formatOutput(result, globalOpts.format as OutputFormat); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); diff --git a/src/cli/commands/bundles.ts b/src/cli/commands/bundles.ts new file mode 100644 index 0000000..cb62167 --- /dev/null +++ b/src/cli/commands/bundles.ts @@ -0,0 +1,228 @@ +/** + * Bundle commands - manage media bundles and product discovery + */ + +import { Command } from 'commander'; +import { createClient, GlobalOptions, parseJsonArg } from '../utils'; +import { formatOutput, printError, printSuccess, OutputFormat } from '../format'; +import type { + CreateBundleInput, + DiscoverProductsParams, + BrowseProductsInput, + AddBundleProductsInput, + BundleProductInput, + RemoveBundleProductsInput, +} from '../../types'; + +export const bundlesCommand = new Command('bundles').description( + 'Manage media bundles and product discovery' +); + +/** + * Create a bundle + */ +bundlesCommand + .command('create') + .description('Create a new media bundle') + .requiredOption('--advertiser-id ', 'Advertiser ID') + .option('--channels ', 'Comma-separated list of channels (e.g., ctv,display)') + .option('--countries ', 'Comma-separated list of country codes (e.g., US,CA)') + .option('--brief ', 'Campaign brief/description') + .option('--budget ', 'Budget amount') + .option('--start-date ', 'Flight start date (ISO format)') + .option('--end-date ', 'Flight end date (ISO format)') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const data: CreateBundleInput = { + advertiserId: options.advertiserId, + }; + + if (options.channels) { + data.channels = options.channels.split(',').map((c: string) => c.trim()); + } + if (options.countries) { + data.countries = options.countries.split(',').map((c: string) => c.trim()); + } + if (options.brief) { + data.brief = options.brief; + } + if (options.budget) { + data.budget = parseFloat(options.budget); + } + if (options.startDate && options.endDate) { + data.flightDates = { + startDate: options.startDate, + endDate: options.endDate, + }; + } + + const result = await client.bundles.create(data); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess(`Created bundle: ${result.data.bundleId}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Discover products for a bundle + */ +bundlesCommand + .command('discover-products ') + .description('Discover available products for a bundle') + .option('--group-limit ', 'Max groups to return (default: 10, max: 50)') + .option('--group-offset ', 'Groups to skip for pagination') + .option('--products-per-group ', 'Products per group (default: 5, max: 50)') + .option('--publisher-domain ', 'Filter by publisher domain') + .action(async (bundleId: string, options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const params: DiscoverProductsParams = {}; + + if (options.groupLimit) { + params.groupLimit = parseInt(options.groupLimit, 10); + } + if (options.groupOffset) { + params.groupOffset = parseInt(options.groupOffset, 10); + } + if (options.productsPerGroup) { + params.productsPerGroup = parseInt(options.productsPerGroup, 10); + } + if (options.publisherDomain) { + params.publisherDomain = options.publisherDomain; + } + + const result = await client.bundles.discoverProducts(bundleId, params); + formatOutput(result, globalOpts.format as OutputFormat); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Browse products without an existing bundle + */ +bundlesCommand + .command('browse-products') + .description('Browse available products without creating a bundle') + .requiredOption('--advertiser-id ', 'Advertiser ID') + .option('--channels ', 'Comma-separated list of channels') + .option('--countries ', 'Comma-separated list of country codes') + .option('--brief ', 'Campaign brief for context') + .option('--publisher-domain ', 'Filter by publisher domain') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const data: BrowseProductsInput = { + advertiserId: options.advertiserId, + }; + + if (options.channels) { + data.channels = options.channels.split(',').map((c: string) => c.trim()); + } + if (options.countries) { + data.countries = options.countries.split(',').map((c: string) => c.trim()); + } + if (options.brief) { + data.brief = options.brief; + } + if (options.publisherDomain) { + data.publisherDomain = options.publisherDomain; + } + + const result = await client.bundles.browseProducts(data); + formatOutput(result, globalOpts.format as OutputFormat); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +// Products sub-commands for bundles +const productsCommand = bundlesCommand.command('products').description('Manage bundle products'); + +/** + * List bundle products + */ +productsCommand + .command('list ') + .description('List all products in a bundle') + .action(async (bundleId: string, _options: unknown, cmd: Command) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.bundles.products(bundleId).list(); + formatOutput(result, globalOpts.format as OutputFormat); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Add products to a bundle + */ +productsCommand + .command('add ') + .description('Add products to a bundle') + .requiredOption( + '--products ', + 'Products to add as JSON string (array of {productId, salesAgentId, groupId, groupName, cpm?, budget?})' + ) + .action(async (bundleId: string, options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const parsed = parseJsonArg(options.products); + if (typeof parsed === 'string') { + printError('Invalid JSON for --products. Expected an array of product objects.'); + process.exit(1); + } + + const data: AddBundleProductsInput = { + products: parsed, + }; + + const result = await client.bundles.products(bundleId).add(data); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess(`Added ${data.products.length} product(s) to bundle`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Remove products from a bundle + */ +productsCommand + .command('remove ') + .description('Remove products from a bundle') + .requiredOption('--product-ids ', 'Comma-separated list of product IDs to remove') + .action(async (bundleId: string, options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const data: RemoveBundleProductsInput = { + productIds: options.productIds.split(',').map((id: string) => id.trim()), + }; + + await client.bundles.products(bundleId).remove(data); + printSuccess(`Removed ${data.productIds.length} product(s) from bundle`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); diff --git a/src/cli/commands/campaigns.ts b/src/cli/commands/campaigns.ts new file mode 100644 index 0000000..2938256 --- /dev/null +++ b/src/cli/commands/campaigns.ts @@ -0,0 +1,459 @@ +/** + * Campaign commands - supports bundle, performance, and audience campaign types + */ + +import { Command } from 'commander'; +import { createClient, GlobalOptions } from '../utils'; +import { formatOutput, printError, printSuccess, OutputFormat } from '../format'; +import type { + CreateBundleCampaignInput, + CreatePerformanceCampaignInput, + CreateAudienceCampaignInput, + UpdateBundleCampaignInput, + UpdatePerformanceCampaignInput, + FlightDates, + Budget, + CampaignConstraints, + PerformanceConfig, + PerformanceObjective, + CampaignType, + CampaignStatus, +} from '../../types'; + +export const campaignsCommand = new Command('campaigns').description('Manage campaigns'); + +/** + * List campaigns + */ +campaignsCommand + .command('list') + .description('List all campaigns') + .option('--take ', 'Maximum number of results', '50') + .option('--skip ', 'Number of results to skip', '0') + .option('--advertiser-id ', 'Filter by advertiser ID') + .option('--type ', 'Filter by type (bundle, performance, audience)') + .option('--status ', 'Filter by status (DRAFT, ACTIVE, PAUSED, COMPLETED, ARCHIVED)') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.campaigns.list({ + take: parseInt(options.take, 10), + skip: parseInt(options.skip, 10), + advertiserId: options.advertiserId, + type: options.type as CampaignType | undefined, + status: options.status as CampaignStatus | undefined, + }); + + formatOutput(result, globalOpts.format as OutputFormat); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Get campaign by ID + */ +campaignsCommand + .command('get ') + .description('Get campaign by ID') + .action(async (id: string, _options: unknown, cmd: Command) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.campaigns.get(id); + formatOutput(result, globalOpts.format as OutputFormat); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Create a bundle campaign + */ +campaignsCommand + .command('create-bundle') + .description('Create a new bundle campaign') + .requiredOption('--advertiser-id ', 'Advertiser ID') + .requiredOption('--name ', 'Campaign name') + .requiredOption('--bundle-id ', 'Bundle ID for inventory selection') + .requiredOption('--start-date ', 'Start date (ISO format)') + .requiredOption('--end-date ', 'End date (ISO format)') + .requiredOption('--budget ', 'Total budget amount') + .option('--currency ', 'Budget currency (default: USD)', 'USD') + .option('--pacing ', 'Budget pacing (EVEN, ASAP, FRONTLOADED)', 'EVEN') + .option('--daily-cap ', 'Daily spending cap') + .option('--brief ', 'Campaign brief/description') + .option('--channels ', 'Comma-separated list of channels (e.g., ctv,display)') + .option('--countries ', 'Comma-separated list of country codes (e.g., US,CA)') + .option('--product-ids ', 'Comma-separated list of product IDs to include') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const flightDates: FlightDates = { + startDate: options.startDate, + endDate: options.endDate, + }; + + const budget: Budget = { + total: parseFloat(options.budget), + currency: options.currency, + pacing: options.pacing, + }; + + if (options.dailyCap) { + budget.dailyCap = parseFloat(options.dailyCap); + } + + const constraints: CampaignConstraints = {}; + if (options.channels) { + constraints.channels = options.channels.split(',').map((c: string) => c.trim()); + } + if (options.countries) { + constraints.countries = options.countries.split(',').map((c: string) => c.trim()); + } + + const data: CreateBundleCampaignInput = { + advertiserId: options.advertiserId, + name: options.name, + bundleId: options.bundleId, + flightDates, + budget, + brief: options.brief, + constraints: Object.keys(constraints).length > 0 ? constraints : undefined, + }; + + if (options.productIds) { + data.productIds = options.productIds.split(',').map((id: string) => id.trim()); + } + + const result = await client.campaigns.createBundle(data); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess(`Created bundle campaign: ${result.data.id}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Create a performance campaign + */ +campaignsCommand + .command('create-performance') + .description('Create a new performance campaign') + .requiredOption('--advertiser-id ', 'Advertiser ID') + .requiredOption('--name ', 'Campaign name') + .requiredOption('--start-date ', 'Start date (ISO format)') + .requiredOption('--end-date ', 'End date (ISO format)') + .requiredOption('--budget ', 'Total budget amount') + .requiredOption( + '--objective ', + 'Performance objective (ROAS, CONVERSIONS, LEADS, SALES)' + ) + .option('--currency ', 'Budget currency (default: USD)', 'USD') + .option('--pacing ', 'Budget pacing (EVEN, ASAP, FRONTLOADED)', 'EVEN') + .option('--daily-cap ', 'Daily spending cap') + .option('--target-roas ', 'Target ROAS for optimization') + .option('--channels ', 'Comma-separated list of channels') + .option('--countries ', 'Comma-separated list of country codes') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const flightDates: FlightDates = { + startDate: options.startDate, + endDate: options.endDate, + }; + + const budget: Budget = { + total: parseFloat(options.budget), + currency: options.currency, + pacing: options.pacing, + }; + + if (options.dailyCap) { + budget.dailyCap = parseFloat(options.dailyCap); + } + + const performanceConfig: PerformanceConfig = { + objective: options.objective as PerformanceObjective, + }; + + if (options.targetRoas) { + performanceConfig.goals = { + targetRoas: parseFloat(options.targetRoas), + }; + } + + const constraints: CampaignConstraints = {}; + if (options.channels) { + constraints.channels = options.channels.split(',').map((c: string) => c.trim()); + } + if (options.countries) { + constraints.countries = options.countries.split(',').map((c: string) => c.trim()); + } + + const data: CreatePerformanceCampaignInput = { + advertiserId: options.advertiserId, + name: options.name, + flightDates, + budget, + performanceConfig, + constraints: Object.keys(constraints).length > 0 ? constraints : undefined, + }; + + const result = await client.campaigns.createPerformance(data); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess(`Created performance campaign: ${result.data.id}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Create an audience campaign + */ +campaignsCommand + .command('create-audience') + .description('Create a new audience campaign') + .requiredOption('--advertiser-id ', 'Advertiser ID') + .requiredOption('--name ', 'Campaign name') + .requiredOption('--start-date ', 'Start date (ISO format)') + .requiredOption('--end-date ', 'End date (ISO format)') + .requiredOption('--budget ', 'Total budget amount') + .option('--currency ', 'Budget currency (default: USD)', 'USD') + .option('--pacing ', 'Budget pacing (EVEN, ASAP, FRONTLOADED)', 'EVEN') + .option('--daily-cap ', 'Daily spending cap') + .option('--signals ', 'Comma-separated list of signal IDs') + .option('--channels ', 'Comma-separated list of channels') + .option('--countries ', 'Comma-separated list of country codes') + .action(async (options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const flightDates: FlightDates = { + startDate: options.startDate, + endDate: options.endDate, + }; + + const budget: Budget = { + total: parseFloat(options.budget), + currency: options.currency, + pacing: options.pacing, + }; + + if (options.dailyCap) { + budget.dailyCap = parseFloat(options.dailyCap); + } + + const constraints: CampaignConstraints = {}; + if (options.channels) { + constraints.channels = options.channels.split(',').map((c: string) => c.trim()); + } + if (options.countries) { + constraints.countries = options.countries.split(',').map((c: string) => c.trim()); + } + + const data: CreateAudienceCampaignInput = { + advertiserId: options.advertiserId, + name: options.name, + flightDates, + budget, + constraints: Object.keys(constraints).length > 0 ? constraints : undefined, + }; + + if (options.signals) { + data.signals = options.signals.split(',').map((s: string) => s.trim()); + } + + const result = await client.campaigns.createAudience(data); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess(`Created audience campaign: ${result.data.id}`); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Update a bundle campaign + */ +campaignsCommand + .command('update-bundle ') + .description('Update a bundle campaign') + .option('--name ', 'New name') + .option('--start-date ', 'New start date') + .option('--end-date ', 'New end date') + .option('--budget ', 'New total budget') + .option('--brief ', 'New brief') + .option('--product-ids ', 'Comma-separated list of product IDs') + .option('--channels ', 'Comma-separated list of channels') + .option('--countries ', 'Comma-separated list of country codes') + .action(async (id: string, options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const data: UpdateBundleCampaignInput = {}; + + if (options.name) data.name = options.name; + if (options.brief) data.brief = options.brief; + + if (options.startDate || options.endDate) { + data.flightDates = {} as FlightDates; + if (options.startDate) data.flightDates.startDate = options.startDate; + if (options.endDate) data.flightDates.endDate = options.endDate; + } + + if (options.budget) { + data.budget = { total: parseFloat(options.budget) }; + } + + if (options.productIds) { + data.productIds = options.productIds.split(',').map((pid: string) => pid.trim()); + } + + const constraints: CampaignConstraints = {}; + if (options.channels) { + constraints.channels = options.channels.split(',').map((c: string) => c.trim()); + } + if (options.countries) { + constraints.countries = options.countries.split(',').map((c: string) => c.trim()); + } + if (Object.keys(constraints).length > 0) { + data.constraints = constraints; + } + + if (Object.keys(data).length === 0) { + printError('No update fields provided'); + process.exit(1); + } + + const result = await client.campaigns.updateBundle(id, data); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess('Bundle campaign updated'); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Update a performance campaign + */ +campaignsCommand + .command('update-performance ') + .description('Update a performance campaign') + .option('--name ', 'New name') + .option('--start-date ', 'New start date') + .option('--end-date ', 'New end date') + .option('--budget ', 'New total budget') + .option('--objective ', 'New performance objective (ROAS, CONVERSIONS, LEADS, SALES)') + .option('--target-roas ', 'New target ROAS') + .option('--channels ', 'Comma-separated list of channels') + .option('--countries ', 'Comma-separated list of country codes') + .action(async (id: string, options, cmd) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const data: UpdatePerformanceCampaignInput = {}; + + if (options.name) data.name = options.name; + + if (options.startDate || options.endDate) { + data.flightDates = {} as FlightDates; + if (options.startDate) data.flightDates.startDate = options.startDate; + if (options.endDate) data.flightDates.endDate = options.endDate; + } + + if (options.budget) { + data.budget = { total: parseFloat(options.budget) }; + } + + if (options.objective || options.targetRoas) { + data.performanceConfig = {} as PerformanceConfig; + if (options.objective) { + data.performanceConfig.objective = options.objective as PerformanceObjective; + } + if (options.targetRoas) { + data.performanceConfig.goals = { + targetRoas: parseFloat(options.targetRoas), + }; + } + } + + const constraints: CampaignConstraints = {}; + if (options.channels) { + constraints.channels = options.channels.split(',').map((c: string) => c.trim()); + } + if (options.countries) { + constraints.countries = options.countries.split(',').map((c: string) => c.trim()); + } + if (Object.keys(constraints).length > 0) { + data.constraints = constraints; + } + + if (Object.keys(data).length === 0) { + printError('No update fields provided'); + process.exit(1); + } + + const result = await client.campaigns.updatePerformance(id, data); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess('Performance campaign updated'); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Execute campaign + */ +campaignsCommand + .command('execute ') + .description('Execute a campaign (go live)') + .action(async (id: string, _options: unknown, cmd: Command) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.campaigns.execute(id); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess('Campaign executed'); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); + +/** + * Pause campaign + */ +campaignsCommand + .command('pause ') + .description('Pause an active campaign') + .action(async (id: string, _options: unknown, cmd: Command) => { + try { + const globalOpts = cmd.optsWithGlobals() as GlobalOptions; + const client = createClient(globalOpts); + + const result = await client.campaigns.pause(id); + formatOutput(result, globalOpts.format as OutputFormat); + printSuccess('Campaign paused'); + } catch (error) { + printError(error instanceof Error ? error.message : 'Unknown error'); + process.exit(1); + } + }); diff --git a/src/cli/commands/config.ts b/src/cli/commands/config.ts new file mode 100644 index 0000000..11f5951 --- /dev/null +++ b/src/cli/commands/config.ts @@ -0,0 +1,114 @@ +/** + * Config commands for managing CLI configuration + */ + +import * as path from 'path'; +import * as os from 'os'; +import { Command } from 'commander'; +import chalk from 'chalk'; +import { loadConfig, saveConfig, clearConfig, getConfigForDisplay } from '../utils'; + +export const configCommand = new Command('config').description('Manage CLI configuration'); + +/** + * Set a config value + */ +configCommand + .command('set ') + .description('Set a configuration value') + .action((key: string, value: string) => { + const validKeys = ['apiKey', 'version', 'environment', 'baseUrl', 'persona']; + + if (!validKeys.includes(key)) { + console.error(chalk.red(`Invalid config key: ${key}`)); + console.error(`Valid keys: ${validKeys.join(', ')}`); + process.exit(1); + } + + // Validate version + if (key === 'version' && !['v1', 'v2', 'latest'].includes(value)) { + console.error(chalk.red(`Invalid version: ${value}`)); + console.error('Valid versions: v1, v2, latest'); + process.exit(1); + } + + // Validate environment + if (key === 'environment' && !['production', 'staging'].includes(value)) { + console.error(chalk.red(`Invalid environment: ${value}`)); + console.error('Valid environments: production, staging'); + process.exit(1); + } + + // Validate persona + if (key === 'persona' && !['buyer', 'brand', 'partner'].includes(value)) { + console.error(chalk.red(`Invalid persona: ${value}`)); + console.error('Valid personas: buyer, brand, partner'); + process.exit(1); + } + + const config = loadConfig(); + (config as Record)[key] = value; + saveConfig(config); + + console.log(chalk.green(`Set ${key}`)); + + // Security notice for API key + if (key === 'apiKey') { + console.log(chalk.yellow('\nSecurity Notice:')); + console.log('API key stored in ~/.scope3/config.json with permissions 0600 (owner only)'); + } + }); + +/** + * Get config values + */ +configCommand + .command('get [key]') + .description('Get configuration value(s)') + .action((key?: string) => { + const config = loadConfig(); + const display = getConfigForDisplay(config); + + if (key) { + if (!(key in config)) { + console.log(chalk.gray('Not set')); + return; + } + console.log((display as Record)[key] ?? chalk.gray('Not set')); + } else { + // Show all config + console.log(chalk.cyan('Current configuration:')); + for (const [k, v] of Object.entries(display)) { + if (v !== undefined) { + console.log(` ${chalk.yellow(k)}: ${v}`); + } + } + + const hasConfig = Object.values(display).some((v) => v !== undefined); + if (!hasConfig) { + console.log(chalk.gray(' No configuration set')); + } + } + }); + +/** + * Clear all config + */ +configCommand + .command('clear') + .description('Clear all configuration') + .action(() => { + clearConfig(); + console.log(chalk.green('Configuration cleared')); + }); + +/** + * Show config file path + */ +configCommand + .command('path') + .description('Show configuration file path') + .action(() => { + const configPath = path.join(os.homedir(), '.scope3', 'config.json'); + console.log(configPath); + }); diff --git a/src/cli/commands/index.ts b/src/cli/commands/index.ts new file mode 100644 index 0000000..d0947d8 --- /dev/null +++ b/src/cli/commands/index.ts @@ -0,0 +1,9 @@ +/** + * CLI command exports + */ + +export { advertisersCommand } from './advertisers'; +export { brandsCommand } from './brands'; +export { bundlesCommand } from './bundles'; +export { campaignsCommand } from './campaigns'; +export { configCommand } from './config'; diff --git a/src/cli/format.ts b/src/cli/format.ts new file mode 100644 index 0000000..7a7c346 --- /dev/null +++ b/src/cli/format.ts @@ -0,0 +1,273 @@ +/** + * CLI output formatting utilities + */ + +import chalk from 'chalk'; +import Table from 'cli-table3'; + +export type OutputFormat = 'json' | 'table' | 'yaml'; + +/** + * Format and print output based on format type + */ +export function formatOutput(data: unknown, format: OutputFormat = 'table'): void { + if (format === 'json') { + console.log(JSON.stringify(data, null, 2)); + return; + } + + if (format === 'yaml') { + console.log(toYaml(data)); + return; + } + + // Table format (default) + printTable(data); +} + +/** + * Check if a value looks like a paginated API response + * Supports both old format { items, total } and new format { data, pagination } + */ +function isPaginatedResponse( + data: unknown +): data is { + data: unknown[]; + pagination: { total: number; take: number; skip: number; hasMore: boolean }; +} { + if (typeof data !== 'object' || data === null) { + return false; + } + const obj = data as Record; + return ( + 'data' in obj && + Array.isArray(obj.data) && + 'pagination' in obj && + typeof obj.pagination === 'object' && + obj.pagination !== null + ); +} + +/** + * Check if a value looks like a legacy paginated response + */ +function isLegacyPaginatedResponse(data: unknown): data is { items: unknown[]; total?: number } { + if (typeof data !== 'object' || data === null) { + return false; + } + const obj = data as Record; + return 'items' in obj && Array.isArray(obj.items); +} + +/** + * Print data as a table + */ +function printTable(data: unknown): void { + // Handle null/undefined + if (data === null || data === undefined) { + console.log(chalk.gray('No data')); + return; + } + + // Handle arrays (list of items) + if (Array.isArray(data)) { + if (data.length === 0) { + console.log(chalk.gray('No items')); + return; + } + printArrayTable(data); + return; + } + + // Handle new paginated responses { data: [...], pagination: {...} } + if (isPaginatedResponse(data)) { + if (data.data.length === 0) { + console.log(chalk.gray('No items')); + return; + } + printArrayTable(data.data); + const pag = data.pagination; + if (typeof pag.total === 'number') { + console.log(chalk.gray(`\nShowing ${data.data.length} of ${pag.total} items`)); + } + return; + } + + // Handle legacy paginated responses { items: [...], total } + if (isLegacyPaginatedResponse(data)) { + if (data.items.length === 0) { + console.log(chalk.gray('No items')); + return; + } + printArrayTable(data.items); + if (typeof data.total === 'number') { + console.log(chalk.gray(`\nShowing ${data.items.length} of ${data.total} items`)); + } + return; + } + + // Handle single object + if (typeof data === 'object') { + printObjectTable(data as Record); + return; + } + + // Handle primitives + console.log(String(data)); +} + +/** + * Print an array of objects as a table + */ +function printArrayTable(items: unknown[]): void { + if (items.length === 0) return; + + // Get keys from first item + const firstItem = items[0]; + if (typeof firstItem !== 'object' || firstItem === null) { + items.forEach((item) => console.log(String(item))); + return; + } + + const keys = Object.keys(firstItem as Record); + + // Select columns: priority keys first, then remaining, max 6 total + const priorityKeys = ['id', 'name', 'status', 'type', 'createdAt', 'updatedAt']; + const displayKeys = [ + ...priorityKeys.filter((k) => keys.includes(k)), + ...keys.filter((k) => !priorityKeys.includes(k)), + ].slice(0, 6); + + const table = new Table({ + head: displayKeys.map((k) => chalk.cyan(k)), + wordWrap: true, + wrapOnWordBoundary: false, + }); + + for (const item of items) { + const row = displayKeys.map((key) => { + const value = (item as Record)[key]; + return formatValue(value); + }); + table.push(row); + } + + console.log(table.toString()); +} + +/** + * Print a single object as a vertical table + */ +function printObjectTable(obj: Record): void { + const table = new Table(); + + for (const [key, value] of Object.entries(obj)) { + table.push({ + [chalk.cyan(key)]: formatValue(value), + }); + } + + console.log(table.toString()); +} + +/** + * Format a value for display in a table + */ +function formatValue(value: unknown): string { + if (value === null || value === undefined) { + return chalk.gray('-'); + } + + if (typeof value === 'boolean') { + return value ? chalk.green('true') : chalk.red('false'); + } + + if (typeof value === 'number') { + return chalk.yellow(String(value)); + } + + if (Array.isArray(value)) { + if (value.length === 0) return chalk.gray('[]'); + if (value.length <= 3 && value.every((v) => typeof v !== 'object')) { + return value.join(', '); + } + return chalk.gray(`[${value.length} items]`); + } + + if (typeof value === 'object') { + const keys = Object.keys(value as Record); + if (keys.length <= 2) { + return JSON.stringify(value); + } + return chalk.gray(`{${keys.length} fields}`); + } + + // Truncate long strings + const str = String(value); + if (str.length > 50) { + return str.slice(0, 47) + '...'; + } + + return str; +} + +/** + * Convert data to YAML-like format + */ +function toYaml(data: unknown, indent = 0): string { + const prefix = ' '.repeat(indent); + + if (data === null || data === undefined) { + return `${prefix}null`; + } + + if (typeof data === 'boolean' || typeof data === 'number') { + return `${prefix}${data}`; + } + + if (typeof data === 'string') { + if (data.includes('\n')) { + return `${prefix}|\n${data + .split('\n') + .map((line) => `${prefix} ${line}`) + .join('\n')}`; + } + return `${prefix}${data}`; + } + + if (Array.isArray(data)) { + if (data.length === 0) return `${prefix}[]`; + return data.map((item) => `${prefix}- ${toYaml(item, indent + 1).trim()}`).join('\n'); + } + + if (typeof data === 'object') { + const entries = Object.entries(data as Record); + if (entries.length === 0) return `${prefix}{}`; + return entries + .map(([key, value]) => `${prefix}${key}: ${toYaml(value, indent + 1).trim()}`) + .join('\n'); + } + + return `${prefix}${String(data)}`; +} + +/** + * Print an error message + */ +export function printError(message: string): void { + console.error(chalk.red(`Error: ${message}`)); +} + +/** + * Print a success message + */ +export function printSuccess(message: string): void { + console.log(chalk.green(message)); +} + +/** + * Print a warning message + */ +export function printWarning(message: string): void { + console.log(chalk.yellow(`Warning: ${message}`)); +} diff --git a/src/cli/index.ts b/src/cli/index.ts new file mode 100644 index 0000000..95465cc --- /dev/null +++ b/src/cli/index.ts @@ -0,0 +1,59 @@ +#!/usr/bin/env node + +/** + * Scope3 CLI - Command line interface for the Scope3 Agentic Platform + * + * Usage: + * scope3 [options] + * + * Examples: + * scope3 config set apiKey sk_xxx + * scope3 --persona buyer advertisers list + * scope3 --persona brand brands list + * scope3 campaigns create-bundle --advertiser-id xxx --bundle-id yyy --name "Q1 Campaign" + * scope3 bundles create --advertiser-id xxx --channels ctv,display + */ + +import { Command } from 'commander'; +import { + advertisersCommand, + brandsCommand, + bundlesCommand, + campaignsCommand, + configCommand, +} from './commands'; + +const program = new Command(); + +program + .name('scope3') + .description('Scope3 Agentic Platform CLI') + .version('2.0.0', '-V, --cli-version') + .option('--api-key ', 'API key for authentication') + .option('--api-version ', 'API version: v1, v2, or latest', 'v2') + .option('--environment ', 'Environment: production or staging', 'production') + .option('--base-url ', 'Custom API base URL') + .option('--format ', 'Output format: json, table, or yaml', 'table') + .option('--debug', 'Enable debug mode') + .option('--persona ', 'API persona: buyer, brand, or partner', 'buyer'); + +// Add commands +program.addCommand(advertisersCommand); +program.addCommand(brandsCommand); +program.addCommand(bundlesCommand); +program.addCommand(campaignsCommand); +program.addCommand(configCommand); + +// Error handling +program.exitOverride((err) => { + if (err.code === 'commander.help') { + process.exit(0); + } + if (err.code === 'commander.version') { + process.exit(0); + } + process.exit(1); +}); + +// Parse and execute +program.parse(); diff --git a/src/cli/utils.ts b/src/cli/utils.ts new file mode 100644 index 0000000..434da0b --- /dev/null +++ b/src/cli/utils.ts @@ -0,0 +1,140 @@ +/** + * CLI utility functions + */ + +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +import { Scope3Client } from '../client'; +import type { Scope3ClientConfig, ApiVersion, Environment, Persona } from '../types'; + +/** + * CLI configuration + */ +export interface CliConfig { + apiKey?: string; + version?: ApiVersion; + environment?: Environment; + baseUrl?: string; + persona?: Persona; +} + +/** + * Global CLI options from commander + */ +export interface GlobalOptions { + apiKey?: string; + apiVersion?: string; + environment?: string; + baseUrl?: string; + format?: string; + debug?: boolean; + persona?: string; +} + +// Config file paths +const CONFIG_DIR = path.join(os.homedir(), '.scope3'); +const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json'); + +/** + * Load CLI configuration from file + */ +export function loadConfig(): CliConfig { + try { + if (fs.existsSync(CONFIG_FILE)) { + const content = fs.readFileSync(CONFIG_FILE, 'utf-8'); + return JSON.parse(content) as CliConfig; + } + } catch (error) { + // Ignore errors, return empty config + } + return {}; +} + +/** + * Save CLI configuration to file + */ +export function saveConfig(config: CliConfig): void { + // Create directory if it doesn't exist + if (!fs.existsSync(CONFIG_DIR)) { + fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 }); + } + + // Write config file with restricted permissions + fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 }); +} + +/** + * Clear CLI configuration + */ +export function clearConfig(): void { + if (fs.existsSync(CONFIG_FILE)) { + fs.unlinkSync(CONFIG_FILE); + } +} + +/** + * Get config value for display (redact sensitive values) + */ +export function getConfigForDisplay(config: CliConfig): Record { + return { + apiKey: config.apiKey ? `${config.apiKey.slice(0, 8)}...${config.apiKey.slice(-4)}` : undefined, + version: config.version, + environment: config.environment, + baseUrl: config.baseUrl, + persona: config.persona, + }; +} + +/** + * Create a Scope3Client from CLI options + */ +export function createClient(options: GlobalOptions): Scope3Client { + const config = loadConfig(); + + // Resolve API key (CLI flag > config > env var) + const apiKey = options.apiKey || config.apiKey || process.env.SCOPE3_API_KEY; + + if (!apiKey) { + throw new Error( + 'API key required. Set via:\n' + + ' - CLI flag: --api-key \n' + + ' - Config: scope3 config set apiKey \n' + + ' - Environment: SCOPE3_API_KEY=' + ); + } + + // Resolve persona (CLI flag > config > default 'buyer') + const persona = (options.persona || config.persona || 'buyer') as Persona; + + // Resolve other options + const version = (options.apiVersion || config.version || 'v2') as ApiVersion; + const environment = (options.environment || config.environment || 'production') as Environment; + const baseUrl = options.baseUrl || config.baseUrl; + + const clientConfig: Scope3ClientConfig = { + apiKey, + persona, + version, + environment, + debug: options.debug, + }; + + if (baseUrl) { + clientConfig.baseUrl = baseUrl; + } + + return new Scope3Client(clientConfig); +} + +/** + * Parse a JSON string into an object + * Returns the original string if parsing fails + */ +export function parseJsonArg(value: string): T | string { + try { + return JSON.parse(value) as T; + } catch { + return value; + } +} diff --git a/src/client.ts b/src/client.ts index 4422d93..9f04691 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,214 +1,208 @@ -import { Client } from '@modelcontextprotocol/sdk/client/index.js'; -import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; -import { ClientConfig, Environment, DebugInfo } from './types'; -import { logger } from './utils/logger'; - +/** + * Scope3Client - Unified client for the Scope3 Agentic Platform + * + * Supports both REST (for humans/CLI) and MCP (for AI agents) adapters. + * Requires a persona to determine which API surface to use. + */ + +import type { Scope3ClientConfig, ApiVersion, Persona } from './types'; +import { BaseAdapter } from './adapters/base'; +import { RestAdapter } from './adapters/rest'; +import { McpAdapter } from './adapters/mcp'; +import { AdvertisersResource } from './resources/advertisers'; +import { BuyerBrandsResource } from './resources/brands'; +import { CampaignsResource } from './resources/campaigns'; +import { BundlesResource } from './resources/bundles'; +import { SignalsResource } from './resources/signals'; +import { BrandBrandsResource } from './resources/brand-brands'; +import { PartnerHealthResource } from './resources/partner-health'; +import { fetchSkillMd, parseSkillMd, ParsedSkill } from './skill'; + +/** + * Main client for interacting with the Scope3 Agentic Platform + * + * @example + * ```typescript + * // Buyer persona + * const client = new Scope3Client({ apiKey: 'token', persona: 'buyer' }); + * const advertisers = await client.advertisers.list(); + * const bundle = await client.bundles.create({ advertiserId: '123', channels: ['display'] }); + * + * // Brand persona + * const brandClient = new Scope3Client({ apiKey: 'token', persona: 'brand' }); + * const brands = await brandClient.brands.list(); + * + * // Partner persona + * const partnerClient = new Scope3Client({ apiKey: 'token', persona: 'partner' }); + * const health = await partnerClient.health.check(); + * ``` + */ export class Scope3Client { - protected readonly mcpClient: Client; - protected readonly apiKey: string; - protected readonly baseUrl: string; - protected readonly debug: boolean; - private transport?: StreamableHTTPClientTransport; - private connected = false; - public lastDebugInfo?: DebugInfo; - - constructor(config: ClientConfig) { - this.apiKey = config.apiKey; - this.debug = config.debug || false; - - // Enable logger debug mode if debug is enabled - if (this.debug) { - logger.setDebug(true); - } + // Buyer persona resources + private _advertisers?: AdvertisersResource; + private _buyerBrands?: BuyerBrandsResource; + private _campaigns?: CampaignsResource; + private _bundles?: BundlesResource; + private _signals?: SignalsResource; - // Priority: explicit baseUrl > environment > default to production - const baseURL = config.baseUrl || this.getDefaultBaseUrl(config.environment || 'production'); - this.baseUrl = baseURL; - - logger.info('Initializing Scope3 client', { - baseUrl: baseURL, - environment: config.environment || 'production', - isCustomUrl: !!config.baseUrl, - debug: this.debug, - }); - - this.mcpClient = new Client( - { - name: '@scope3/agentic-client', - version: '0.1.0', - }, - { - capabilities: { - tools: {}, - }, - } - ); - - this.transport = new StreamableHTTPClientTransport(new URL(`${baseURL}/mcp`), { - requestInit: { - headers: { - 'x-scope3-api-key': this.apiKey, - }, - }, - }); - } + // Brand persona resources + private _brandBrands?: BrandBrandsResource; - private getDefaultBaseUrl(env: Environment): string { - return env === 'production' - ? 'https://api.agentic.scope3.com' - : 'https://api.agentic.staging.scope3.com'; - } + // Partner persona resources + private _health?: PartnerHealthResource; - async connect(): Promise { - if (this.connected || !this.transport) { - return; + /** The adapter used for API communication */ + private readonly adapter: BaseAdapter; + + /** API version being used */ + public readonly version: ApiVersion; + + /** API persona being used */ + public readonly persona: Persona; + + /** Cached parsed skill.md */ + private skillPromise: Promise | null = null; + + constructor(config: Scope3ClientConfig) { + if (!config.apiKey) { + throw new Error('apiKey is required'); + } + if (!config.persona) { + throw new Error('persona is required (buyer, brand, or partner)'); } - await this.mcpClient.connect(this.transport); - this.connected = true; - } + this.version = config.version ?? 'v2'; + this.persona = config.persona; - async disconnect(): Promise { - if (!this.connected) { - return; + // Select adapter based on config + if (config.adapter === 'mcp') { + this.adapter = new McpAdapter(config); + } else { + this.adapter = new RestAdapter(config); } - await this.mcpClient.close(); - if (this.transport) { - await this.transport.close(); + // Initialize persona-specific resources + switch (this.persona) { + case 'buyer': + this._advertisers = new AdvertisersResource(this.adapter); + this._buyerBrands = new BuyerBrandsResource(this.adapter); + this._campaigns = new CampaignsResource(this.adapter); + this._bundles = new BundlesResource(this.adapter); + this._signals = new SignalsResource(this.adapter); + break; + case 'brand': + this._brandBrands = new BrandBrandsResource(this.adapter); + break; + case 'partner': + this._health = new PartnerHealthResource(this.adapter); + break; } - this.connected = false; } - private sanitizeForLogging(obj: unknown): unknown { - if (!obj || typeof obj !== 'object') { - return obj; + // โ”€โ”€ Buyer persona resources โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + /** Advertiser management (buyer persona) */ + get advertisers(): AdvertisersResource { + if (!this._advertisers) { + throw new Error('advertisers is only available with the buyer persona'); } + return this._advertisers; + } - const sensitiveKeys = [ - 'apiKey', - 'api_key', - 'token', - 'password', - 'secret', - 'auth', - 'authorization', - 'credentials', - ]; - - if (Array.isArray(obj)) { - return obj.map((item) => this.sanitizeForLogging(item)); + /** Brand listing for buyers (buyer persona) */ + get buyerBrands(): BuyerBrandsResource { + if (!this._buyerBrands) { + throw new Error('buyerBrands is only available with the buyer persona'); } + return this._buyerBrands; + } - const sanitized: Record = {}; - for (const [key, value] of Object.entries(obj)) { - if (sensitiveKeys.some((k) => key.toLowerCase().includes(k))) { - sanitized[key] = '[REDACTED]'; - } else if (typeof value === 'object' && value !== null) { - sanitized[key] = this.sanitizeForLogging(value); - } else { - sanitized[key] = value; - } + /** Campaign management (buyer persona) */ + get campaigns(): CampaignsResource { + if (!this._campaigns) { + throw new Error('campaigns is only available with the buyer persona'); } - return sanitized; + return this._campaigns; } - protected async callTool( - toolName: string, - args: TRequest - ): Promise { - const startTime = Date.now(); + /** Bundle management for inventory selection (buyer persona) */ + get bundles(): BundlesResource { + if (!this._bundles) { + throw new Error('bundles is only available with the buyer persona'); + } + return this._bundles; + } - if (!this.connected) { - await this.connect(); + /** Signal discovery (buyer persona) */ + get signals(): SignalsResource { + if (!this._signals) { + throw new Error('signals is only available with the buyer persona'); } + return this._signals; + } - const request = { - name: toolName, - arguments: args as Record, - }; + // โ”€โ”€ Brand persona resources โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - if (this.debug) { - const sanitizedRequest = this.sanitizeForLogging(request); - logger.info('MCP Request', { request: sanitizedRequest }); + /** Brand identity management (brand persona) */ + get brands(): BrandBrandsResource { + if (!this._brandBrands) { + throw new Error('brands is only available with the brand persona'); } + return this._brandBrands; + } - const result = await this.mcpClient.callTool(request); - const durationMs = Date.now() - startTime; + // โ”€โ”€ Partner persona resources โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - if (this.debug) { - const sanitizedResult = this.sanitizeForLogging(result); - logger.info('MCP Response', { - toolName, - duration: `${durationMs}ms`, - result: sanitizedResult, - }); + /** Health check (partner persona) */ + get health(): PartnerHealthResource { + if (!this._health) { + throw new Error('health is only available with the partner persona'); } + return this._health; + } - // MCP tools MUST return structured content according to Scope3 API spec - // If structuredContent is missing, this is an API bug that needs to be fixed upstream - - // Check for structuredContent (required) - if (result.structuredContent) { - // Extract human-readable message from content if present - const content = result.content as Array<{ type: string; text?: string }> | undefined; - const textMessage = - content && content.length > 0 && content[0].type === 'text' ? content[0].text : undefined; - - // Wrap response with message if it exists - const response = textMessage - ? { _message: textMessage, ...result.structuredContent } - : result.structuredContent; - - if (this.debug) { - this.lastDebugInfo = { - toolName, - request: args as Record, - response, - durationMs, - }; - } - return response as TResponse; + // โ”€โ”€ Shared methods โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + /** + * Get the parsed skill.md for this persona and API version + */ + async getSkill(): Promise { + if (!this.skillPromise) { + this.skillPromise = fetchSkillMd({ + version: this.version, + persona: this.persona, + baseUrl: this.adapter.baseUrl, + }) + .then((content) => parseSkillMd(content)) + .catch((err) => { + this.skillPromise = null; + throw err; + }); } + return this.skillPromise; + } - // FAIL LOUDLY: structuredContent is missing - // This helps catch API bugs that need upstream fixes - const content = result.content as Array<{ type: string; text?: string }> | undefined; - const firstContent = content && content.length > 0 ? content[0] : null; - const textPreview = - firstContent?.type === 'text' && firstContent.text - ? firstContent.text.substring(0, 200) - : undefined; - - // Only log detailed info in debug mode - if (this.debug) { - const errorDetails = { - toolName, - hasContent: Boolean(content), - contentType: firstContent?.type, - textPreview, - }; - logger.error('MCP API VIOLATION: Missing structuredContent', errorDetails); - } + /** + * Connect to the API (required for MCP adapter) + */ + async connect(): Promise { + await this.adapter.connect(); + } - // User-friendly error message - const errorMessage = [ - `API Error: Missing structured data for "${toolName}"`, - textPreview ? `\nAPI returned text: "${textPreview}"` : '', - '\n\nThe API should return structured JSON data but returned only text. ', - 'This is an API bug that needs to be fixed upstream.', - ] - .filter(Boolean) - .join(''); - - throw new Error(errorMessage); + /** + * Disconnect from the API (for cleanup) + */ + async disconnect(): Promise { + await this.adapter.disconnect(); } - protected getClient(): Client { - return this.mcpClient; + /** Get the base URL being used */ + get baseUrl(): string { + return this.adapter.baseUrl; } - public getBaseUrl(): string { - return this.baseUrl; + /** Check if debug mode is enabled */ + get debug(): boolean { + return this.adapter.debug; } } diff --git a/src/index.ts b/src/index.ts index d655bd4..faa59c4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,150 @@ -// Auto-generated clients -export { PlatformClient } from './platform-client'; -export { PartnerClient } from './partner-client'; +/** + * Scope3 SDK - REST and MCP client for the Agentic Platform + * + * Supports 3 personas: buyer, brand, and partner. + * + * @example + * ```typescript + * import { Scope3Client } from 'scope3'; + * + * // Buyer persona + * const buyer = new Scope3Client({ apiKey: 'sk_xxx', persona: 'buyer' }); + * const advertisers = await buyer.advertisers.list(); + * + * // Brand persona + * const brand = new Scope3Client({ apiKey: 'sk_xxx', persona: 'brand' }); + * const brands = await brand.brands.list(); + * + * // Partner persona + * const partner = new Scope3Client({ apiKey: 'sk_xxx', persona: 'partner' }); + * const health = await partner.health.check(); + * ``` + */ -// Standalone services +// Main client +export { Scope3Client } from './client'; + +// Adapters +export { RestAdapter } from './adapters/rest'; +export { McpAdapter } from './adapters/mcp'; +export { Scope3ApiError } from './adapters/base'; +export type { BaseAdapter } from './adapters/base'; + +// Resources +export { + AdvertisersResource, + BuyerBrandsResource, + BuyerLinkedBrandResource, + BrandBrandsResource, + BundlesResource, + BundleProductsResource, + CampaignsResource, + ConversionEventsResource, + CreativeSetsResource, + MediaBuysResource, + PartnerHealthResource, + ReportingResource, + SignalsResource, + TestCohortsResource, +} from './resources'; + +// skill.md support +export { fetchSkillMd, parseSkillMd, getBundledSkillMd } from './skill'; +export type { ParsedSkill, SkillCommand, SkillParameter, SkillExample } from './skill'; + +// Webhook server (optional) export { WebhookServer } from './webhook-server'; +export type { WebhookEvent, WebhookHandler, WebhookServerConfig } from './webhook-server'; // Types -export type { ClientConfig, ToolResponse, Environment } from './types'; -export type { WebhookEvent, WebhookHandler, WebhookServerConfig } from './webhook-server'; +export type { + // Config + Scope3ClientConfig, + ApiVersion, + Persona, + Environment, + AdapterType, + // API Response Wrappers + ApiResponse, + PaginatedApiResponse, + PaginationInfo, + ApiErrorResponse, + // Pagination + PaginationParams, + // Advertiser + Advertiser, + AdvertiserStatus, + CreateAdvertiserInput, + UpdateAdvertiserInput, + ListAdvertisersParams, + // Brand (standalone - brand persona) + Brand, + CreateBrandInput, + UpdateBrandInput, + ListBrandsParams, + BrandManifest, + BrandLogo, + BrandColors, + BrandFonts, + BrandAsset, + // Linked Brand (buyer persona) + LinkedBrand, + LinkBrandInput, + // Campaign + Campaign, + CampaignStatus, + CampaignType, + FlightDates, + Budget, + BudgetPacing, + CampaignConstraints, + PerformanceObjective, + PerformanceConfig, + CreateBundleCampaignInput, + UpdateBundleCampaignInput, + CreatePerformanceCampaignInput, + UpdatePerformanceCampaignInput, + CreateAudienceCampaignInput, + ListCampaignsParams, + // Bundle + Bundle, + CreateBundleInput, + DiscoverProductsParams, + DiscoverProductsResponse, + ProductGroup, + Product, + ProductSummary, + BudgetContext, + BundleProductInput, + AddBundleProductsInput, + RemoveBundleProductsInput, + BundleProductsResponse, + SelectedBundleProduct, + BrowseProductsInput, + // Conversion Events + ConversionEvent, + ConversionEventType, + CreateConversionEventInput, + UpdateConversionEventInput, + // Creative Sets + CreativeSet, + CreateCreativeSetInput, + CreativeAsset, + CreateCreativeAssetInput, + // Test Cohorts + TestCohort, + CreateTestCohortInput, + // Reporting + ReportingParams, + ReportingResponse, + DailyMetric, + MetricTotals, + // Media Buys + MediaBuy, + ListMediaBuysParams, + // Signals + Signal, + DiscoverSignalsInput, + // Partner + HealthCheckResponse, +} from './types'; diff --git a/src/partner-client.ts b/src/partner-client.ts deleted file mode 100644 index 3e6a870..0000000 --- a/src/partner-client.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Scope3Client } from './client'; -import { ClientConfig } from './types'; -import { ChannelsResource } from './resources/partner/channels'; -import { TargetingResource } from './resources/partner/targeting'; -import { CreativesResource } from './resources/partner/creatives'; -import { MediaBuysResource } from './resources/partner/mediaBuys'; -import { NotificationsResource } from './resources/partner/notifications'; -import { MediaProductsResource } from './resources/partner/mediaProducts'; -import { AgentsResource } from './resources/partner/agents'; -import { TacticsResource } from './resources/partner/tactics'; -import { WebhooksResource } from './resources/partner/webhooks'; -import { ServiceTokensResource } from './resources/partner/serviceTokens'; -import { CustomersResource } from './resources/partner/customers'; - -/** - * Scope3 Partner API - * - * API for partners to register agents, manage tactics and media buys, and configure webhooks. - * - * This API provides partners with tools to: - * - Register and manage sales agents (DSPs, publisher platforms) - * - Full CRUD operations for tactics and media buys - * - Link tactics to buyer campaigns (read-only campaign access) - * - Manage media products and product discovery - * - Configure webhooks for event notifications - * - Execute media buys and manage placements - */ -export class PartnerClient extends Scope3Client { - public readonly channels: ChannelsResource; - public readonly targeting: TargetingResource; - public readonly creatives: CreativesResource; - public readonly mediaBuys: MediaBuysResource; - public readonly notifications: NotificationsResource; - public readonly mediaProducts: MediaProductsResource; - public readonly agents: AgentsResource; - public readonly tactics: TacticsResource; - public readonly webhooks: WebhooksResource; - public readonly serviceTokens: ServiceTokensResource; - public readonly customers: CustomersResource; - - constructor(config: ClientConfig) { - super(config); - - this.channels = new ChannelsResource(this); - this.targeting = new TargetingResource(this); - this.creatives = new CreativesResource(this); - this.mediaBuys = new MediaBuysResource(this); - this.notifications = new NotificationsResource(this); - this.mediaProducts = new MediaProductsResource(this); - this.agents = new AgentsResource(this); - this.tactics = new TacticsResource(this); - this.webhooks = new WebhooksResource(this); - this.serviceTokens = new ServiceTokensResource(this); - this.customers = new CustomersResource(this); - } - - // Expose MCP methods for CLI dynamic command generation - async listTools(): Promise { - if (!this.getClient()) { - await this.connect(); - } - return this.getClient().listTools(); - } - - async callTool, TResponse = unknown>( - toolName: string, - args: TRequest - ): Promise { - return super.callTool(toolName, args); - } -} diff --git a/src/platform-client.ts b/src/platform-client.ts deleted file mode 100644 index 7926ca2..0000000 --- a/src/platform-client.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Scope3Client } from './client'; -import { ClientConfig } from './types'; -import { BrandAgentsResource } from './resources/platform/brandAgents'; -import { CampaignsResource } from './resources/platform/campaigns'; -import { AssetsResource } from './resources/platform/assets'; -import { BrandStandardsResource } from './resources/platform/brandStandards'; -import { BrandStoriesResource } from './resources/platform/brandStories'; -import { ChannelsResource } from './resources/platform/channels'; -import { TargetingResource } from './resources/platform/targeting'; -import { CreativesResource } from './resources/platform/creatives'; -import { MediaBuysResource } from './resources/platform/mediaBuys'; -import { MediaProductsResource } from './resources/platform/mediaProducts'; -import { AgentsResource } from './resources/platform/agents'; -import { TacticsResource } from './resources/platform/tactics'; -import { OutcomeAgentsResource } from './resources/platform/outcomeAgents'; -import { ServiceTokensResource } from './resources/platform/serviceTokens'; -import { CustomersResource } from './resources/platform/customers'; - -/** - * Scope3 Platform API - * - * API for brand advertisers to manage brand agents, campaigns, creatives, and discover marketplace offerings. - * - * This API provides buyers with tools to: - * - Manage brand agents and campaign briefs - * - Create and manage creatives - * - Discover and save media products from the marketplace - * - View campaigns, tactics, and media buys (read-only) - * - Configure brand standards and brand stories - */ -export class PlatformClient extends Scope3Client { - public readonly brandAgents: BrandAgentsResource; - public readonly campaigns: CampaignsResource; - public readonly assets: AssetsResource; - public readonly brandStandards: BrandStandardsResource; - public readonly brandStories: BrandStoriesResource; - public readonly channels: ChannelsResource; - public readonly targeting: TargetingResource; - public readonly creatives: CreativesResource; - public readonly mediaBuys: MediaBuysResource; - public readonly mediaProducts: MediaProductsResource; - public readonly agents: AgentsResource; - public readonly tactics: TacticsResource; - public readonly outcomeAgents: OutcomeAgentsResource; - public readonly serviceTokens: ServiceTokensResource; - public readonly customers: CustomersResource; - - constructor(config: ClientConfig) { - super(config); - - this.brandAgents = new BrandAgentsResource(this); - this.campaigns = new CampaignsResource(this); - this.assets = new AssetsResource(this); - this.brandStandards = new BrandStandardsResource(this); - this.brandStories = new BrandStoriesResource(this); - this.channels = new ChannelsResource(this); - this.targeting = new TargetingResource(this); - this.creatives = new CreativesResource(this); - this.mediaBuys = new MediaBuysResource(this); - this.mediaProducts = new MediaProductsResource(this); - this.agents = new AgentsResource(this); - this.tactics = new TacticsResource(this); - this.outcomeAgents = new OutcomeAgentsResource(this); - this.serviceTokens = new ServiceTokensResource(this); - this.customers = new CustomersResource(this); - } - - // Expose MCP methods for CLI dynamic command generation - async listTools(): Promise { - if (!this.getClient()) { - await this.connect(); - } - return this.getClient().listTools(); - } - - async callTool, TResponse = unknown>( - toolName: string, - args: TRequest - ): Promise { - return super.callTool(toolName, args); - } -} diff --git a/src/resources/advertisers.ts b/src/resources/advertisers.ts new file mode 100644 index 0000000..1f2e831 --- /dev/null +++ b/src/resources/advertisers.ts @@ -0,0 +1,144 @@ +/** + * Advertisers resource for managing advertiser accounts + */ + +import { type BaseAdapter, validateResourceId } from '../adapters/base'; +import type { + Advertiser, + CreateAdvertiserInput, + UpdateAdvertiserInput, + ListAdvertisersParams, + PaginatedApiResponse, + ApiResponse, +} from '../types'; +import { BuyerLinkedBrandResource } from './brands'; +import { ConversionEventsResource } from './conversion-events'; +import { CreativeSetsResource } from './creative-sets'; +import { TestCohortsResource } from './test-cohorts'; +import { ReportingResource } from './reporting'; +import { MediaBuysResource } from './media-buys'; + +/** + * Resource for managing advertisers (Buyer persona) + */ +export class AdvertisersResource { + constructor(private readonly adapter: BaseAdapter) {} + + /** + * List all advertisers + * @param params Pagination and filter parameters + * @returns Paginated list of advertisers + */ + async list(params?: ListAdvertisersParams): Promise> { + return this.adapter.request>( + 'GET', + '/advertisers', + undefined, + { + params: { + take: params?.take, + skip: params?.skip, + status: params?.status, + name: params?.name, + }, + } + ); + } + + /** + * Get an advertiser by ID + * @param id Advertiser ID + * @returns Advertiser details + */ + async get(id: string): Promise> { + return this.adapter.request>( + 'GET', + `/advertisers/${validateResourceId(id)}` + ); + } + + /** + * Create a new advertiser + * @param data Advertiser creation data + * @returns Created advertiser + */ + async create(data: CreateAdvertiserInput): Promise> { + return this.adapter.request>('POST', '/advertisers', data); + } + + /** + * Update an existing advertiser + * @param id Advertiser ID + * @param data Update data + * @returns Updated advertiser + */ + async update(id: string, data: UpdateAdvertiserInput): Promise> { + return this.adapter.request>( + 'PUT', + `/advertisers/${validateResourceId(id)}`, + data + ); + } + + /** + * Delete an advertiser + * @param id Advertiser ID + */ + async delete(id: string): Promise { + await this.adapter.request('DELETE', `/advertisers/${validateResourceId(id)}`); + } + + /** + * Get the linked brand resource for a specific advertiser + * @param advertiserId Advertiser ID + * @returns BuyerLinkedBrandResource scoped to the advertiser + */ + brand(advertiserId: string): BuyerLinkedBrandResource { + return new BuyerLinkedBrandResource(this.adapter, validateResourceId(advertiserId)); + } + + /** + * Get the conversion events resource for a specific advertiser + * @param advertiserId Advertiser ID + * @returns ConversionEventsResource scoped to the advertiser + */ + conversionEvents(advertiserId: string): ConversionEventsResource { + return new ConversionEventsResource(this.adapter, validateResourceId(advertiserId)); + } + + /** + * Get the creative sets resource for a specific advertiser + * @param advertiserId Advertiser ID + * @returns CreativeSetsResource scoped to the advertiser + */ + creativeSets(advertiserId: string): CreativeSetsResource { + return new CreativeSetsResource(this.adapter, validateResourceId(advertiserId)); + } + + /** + * Get the test cohorts resource for a specific advertiser + * @param advertiserId Advertiser ID + * @returns TestCohortsResource scoped to the advertiser + */ + testCohorts(advertiserId: string): TestCohortsResource { + return new TestCohortsResource(this.adapter, validateResourceId(advertiserId)); + } + + /** + * Get the reporting resource for a specific advertiser + * @param advertiserId Advertiser ID + * @returns ReportingResource scoped to the advertiser + */ + reporting(advertiserId: string): ReportingResource { + return new ReportingResource(this.adapter, validateResourceId(advertiserId)); + } + + /** + * Get the media buys resource for a specific advertiser + * @param advertiserId Advertiser ID + * @returns MediaBuysResource scoped to the advertiser + */ + mediaBuys(advertiserId: string): MediaBuysResource { + return new MediaBuysResource(this.adapter, validateResourceId(advertiserId)); + } +} diff --git a/src/resources/brand-brands.ts b/src/resources/brand-brands.ts new file mode 100644 index 0000000..e440573 --- /dev/null +++ b/src/resources/brand-brands.ts @@ -0,0 +1,77 @@ +/** + * Brand brands resource for managing brands in the Brand persona + * Not scoped to a specific advertiser + */ + +import { type BaseAdapter, validateResourceId } from '../adapters/base'; +import type { + Brand, + CreateBrandInput, + UpdateBrandInput, + ListBrandsParams, + PaginatedApiResponse, + ApiResponse, +} from '../types'; + +/** + * Resource for managing brands (Brand persona) + */ +export class BrandBrandsResource { + constructor(private readonly adapter: BaseAdapter) {} + + /** + * List all brands + * @param params Pagination parameters + * @returns Paginated list of brands + */ + async list(params?: ListBrandsParams): Promise> { + return this.adapter.request>('GET', '/brands', undefined, { + params: { + take: params?.take, + skip: params?.skip, + status: params?.status, + name: params?.name, + }, + }); + } + + /** + * Get a brand by ID + * @param id Brand ID + * @returns Brand details + */ + async get(id: string): Promise> { + return this.adapter.request>('GET', `/brands/${validateResourceId(id)}`); + } + + /** + * Create a new brand + * @param data Brand creation data + * @returns Created brand + */ + async create(data: CreateBrandInput): Promise> { + return this.adapter.request>('POST', '/brands', data); + } + + /** + * Update an existing brand + * @param id Brand ID + * @param data Brand update data + * @returns Updated brand + */ + async update(id: string, data: UpdateBrandInput): Promise> { + return this.adapter.request>( + 'PUT', + `/brands/${validateResourceId(id)}`, + data + ); + } + + /** + * Delete a brand + * @param id Brand ID + */ + async delete(id: string): Promise { + await this.adapter.request('DELETE', `/brands/${validateResourceId(id)}`); + } +} diff --git a/src/resources/brands.ts b/src/resources/brands.ts new file mode 100644 index 0000000..f305022 --- /dev/null +++ b/src/resources/brands.ts @@ -0,0 +1,80 @@ +/** + * Brand resources for buyer persona + * + * BuyerBrandsResource - flat list of all brands available to the buyer + * BuyerLinkedBrandResource - manage the brand linked to a specific advertiser + */ + +import type { BaseAdapter } from '../adapters/base'; +import type { + Brand, + ListBrandsParams, + LinkedBrand, + LinkBrandInput, + PaginatedApiResponse, + ApiResponse, +} from '../types'; + +/** + * Resource for listing buyer brands (not scoped to an advertiser) + */ +export class BuyerBrandsResource { + constructor(private readonly adapter: BaseAdapter) {} + + /** + * List all brands available to the buyer + * @param params Pagination and filter parameters + * @returns Paginated list of brands + */ + async list(params?: ListBrandsParams): Promise> { + return this.adapter.request>('GET', '/brands', undefined, { + params: { + take: params?.take, + skip: params?.skip, + status: params?.status, + name: params?.name, + }, + }); + } +} + +/** + * Resource for managing the brand linked to a specific advertiser + */ +export class BuyerLinkedBrandResource { + constructor( + private readonly adapter: BaseAdapter, + private readonly advertiserId: string + ) {} + + /** + * Get the brand linked to this advertiser + * @returns Linked brand details + */ + async get(): Promise> { + return this.adapter.request>( + 'GET', + `/advertisers/${this.advertiserId}/brand` + ); + } + + /** + * Link a brand to this advertiser + * @param data Brand link data containing brandId + * @returns Linked brand details + */ + async link(data: LinkBrandInput): Promise> { + return this.adapter.request>( + 'PUT', + `/advertisers/${this.advertiserId}/brand`, + data + ); + } + + /** + * Unlink the brand from this advertiser + */ + async unlink(): Promise { + await this.adapter.request('DELETE', `/advertisers/${this.advertiserId}/brand`); + } +} diff --git a/src/resources/bundles.ts b/src/resources/bundles.ts new file mode 100644 index 0000000..ec95773 --- /dev/null +++ b/src/resources/bundles.ts @@ -0,0 +1,77 @@ +/** + * Bundles resource for creating and managing media bundles + */ + +import { type BaseAdapter, validateResourceId } from '../adapters/base'; +import type { + Bundle, + CreateBundleInput, + DiscoverProductsParams, + DiscoverProductsResponse, + BrowseProductsInput, + ApiResponse, +} from '../types'; +import { BundleProductsResource } from './products'; + +/** + * Resource for managing bundles (Buyer persona) + */ +export class BundlesResource { + constructor(private readonly adapter: BaseAdapter) {} + + /** + * Create a new bundle + * @param data Bundle creation data + * @returns Created bundle with bundleId + */ + async create(data: CreateBundleInput): Promise> { + return this.adapter.request>('POST', '/bundles', data); + } + + /** + * Discover products available for a bundle + * @param bundleId Bundle ID + * @param params Query parameters for pagination and filtering + * @returns Discovered product groups with budget context + */ + async discoverProducts( + bundleId: string, + params?: DiscoverProductsParams + ): Promise> { + return this.adapter.request>( + 'GET', + `/bundles/${validateResourceId(bundleId)}/discover-products`, + undefined, + { + params: { + groupLimit: params?.groupLimit, + groupOffset: params?.groupOffset, + productsPerGroup: params?.productsPerGroup, + publisherDomain: params?.publisherDomain, + }, + } + ); + } + + /** + * Browse products without an existing bundle + * @param data Browse criteria including advertiser, channels, and filters + * @returns Discovered product groups + */ + async browseProducts(data: BrowseProductsInput): Promise> { + return this.adapter.request>( + 'POST', + '/bundles/discover-products', + data + ); + } + + /** + * Get the products resource for a specific bundle + * @param bundleId Bundle ID + * @returns BundleProductsResource scoped to the bundle + */ + products(bundleId: string): BundleProductsResource { + return new BundleProductsResource(this.adapter, validateResourceId(bundleId)); + } +} diff --git a/src/resources/campaigns.ts b/src/resources/campaigns.ts new file mode 100644 index 0000000..68f7dbc --- /dev/null +++ b/src/resources/campaigns.ts @@ -0,0 +1,134 @@ +/** + * Campaigns resource for managing advertising campaigns + */ + +import { type BaseAdapter, validateResourceId } from '../adapters/base'; +import type { + Campaign, + CreateBundleCampaignInput, + UpdateBundleCampaignInput, + CreatePerformanceCampaignInput, + UpdatePerformanceCampaignInput, + CreateAudienceCampaignInput, + ListCampaignsParams, + PaginatedApiResponse, + ApiResponse, +} from '../types'; + +/** + * Resource for managing campaigns (Buyer persona) + */ +export class CampaignsResource { + constructor(private readonly adapter: BaseAdapter) {} + + /** + * List all campaigns + * @param params Pagination and filter parameters + * @returns Paginated list of campaigns + */ + async list(params?: ListCampaignsParams): Promise> { + return this.adapter.request>('GET', '/campaigns', undefined, { + params: { + take: params?.take, + skip: params?.skip, + advertiserId: params?.advertiserId, + type: params?.type, + status: params?.status, + }, + }); + } + + /** + * Get a campaign by ID + * @param id Campaign ID + * @returns Campaign details + */ + async get(id: string): Promise> { + return this.adapter.request>( + 'GET', + `/campaigns/${validateResourceId(id)}` + ); + } + + /** + * Create a new bundle campaign + * @param data Bundle campaign creation data + * @returns Created campaign + */ + async createBundle(data: CreateBundleCampaignInput): Promise> { + return this.adapter.request>('POST', '/campaigns/bundle', data); + } + + /** + * Update an existing bundle campaign + * @param id Campaign ID + * @param data Bundle campaign update data + * @returns Updated campaign + */ + async updateBundle(id: string, data: UpdateBundleCampaignInput): Promise> { + return this.adapter.request>( + 'PUT', + `/campaigns/bundle/${validateResourceId(id)}`, + data + ); + } + + /** + * Create a new performance campaign + * @param data Performance campaign creation data + * @returns Created campaign + */ + async createPerformance(data: CreatePerformanceCampaignInput): Promise> { + return this.adapter.request>('POST', '/campaigns/performance', data); + } + + /** + * Update an existing performance campaign + * @param id Campaign ID + * @param data Performance campaign update data + * @returns Updated campaign + */ + async updatePerformance( + id: string, + data: UpdatePerformanceCampaignInput + ): Promise> { + return this.adapter.request>( + 'PUT', + `/campaigns/performance/${validateResourceId(id)}`, + data + ); + } + + /** + * Create a new audience campaign + * @param data Audience campaign creation data + * @returns Created campaign + */ + async createAudience(data: CreateAudienceCampaignInput): Promise> { + return this.adapter.request>('POST', '/campaigns/audience', data); + } + + /** + * Execute a campaign (go live) + * @param id Campaign ID + * @returns Updated campaign + */ + async execute(id: string): Promise> { + return this.adapter.request>( + 'POST', + `/campaigns/${validateResourceId(id)}/execute` + ); + } + + /** + * Pause an active campaign + * @param id Campaign ID + * @returns Updated campaign + */ + async pause(id: string): Promise> { + return this.adapter.request>( + 'POST', + `/campaigns/${validateResourceId(id)}/pause` + ); + } +} diff --git a/src/resources/conversion-events.ts b/src/resources/conversion-events.ts new file mode 100644 index 0000000..d31229b --- /dev/null +++ b/src/resources/conversion-events.ts @@ -0,0 +1,75 @@ +/** + * Conversion events resource for managing advertiser conversion tracking + * Scoped to a specific advertiser + */ + +import { type BaseAdapter, validateResourceId } from '../adapters/base'; +import type { + ConversionEvent, + CreateConversionEventInput, + UpdateConversionEventInput, + ApiResponse, +} from '../types'; + +/** + * Resource for managing conversion events (scoped to an advertiser) + */ +export class ConversionEventsResource { + constructor( + private readonly adapter: BaseAdapter, + private readonly advertiserId: string + ) {} + + /** + * List all conversion events for this advertiser + * @returns List of conversion events + */ + async list(): Promise> { + return this.adapter.request>( + 'GET', + `/advertisers/${this.advertiserId}/conversion-events` + ); + } + + /** + * Get a conversion event by ID + * @param eventId Conversion event ID + * @returns Conversion event details + */ + async get(eventId: string): Promise> { + return this.adapter.request>( + 'GET', + `/advertisers/${this.advertiserId}/conversion-events/${validateResourceId(eventId)}` + ); + } + + /** + * Create a new conversion event + * @param data Conversion event creation data + * @returns Created conversion event + */ + async create(data: CreateConversionEventInput): Promise> { + return this.adapter.request>( + 'POST', + `/advertisers/${this.advertiserId}/conversion-events`, + data + ); + } + + /** + * Update an existing conversion event + * @param eventId Conversion event ID + * @param data Update data + * @returns Updated conversion event + */ + async update( + eventId: string, + data: UpdateConversionEventInput + ): Promise> { + return this.adapter.request>( + 'PUT', + `/advertisers/${this.advertiserId}/conversion-events/${validateResourceId(eventId)}`, + data + ); + } +} diff --git a/src/resources/creative-sets.ts b/src/resources/creative-sets.ts new file mode 100644 index 0000000..187a9f3 --- /dev/null +++ b/src/resources/creative-sets.ts @@ -0,0 +1,76 @@ +/** + * Creative sets resource for managing advertiser creative assets + * Scoped to a specific advertiser + */ + +import { type BaseAdapter, validateResourceId } from '../adapters/base'; +import type { + CreativeSet, + CreateCreativeSetInput, + CreativeAsset, + CreateCreativeAssetInput, + ApiResponse, +} from '../types'; + +/** + * Resource for managing creative sets (scoped to an advertiser) + */ +export class CreativeSetsResource { + constructor( + private readonly adapter: BaseAdapter, + private readonly advertiserId: string + ) {} + + /** + * List all creative sets for this advertiser + * @returns List of creative sets + */ + async list(): Promise> { + return this.adapter.request>( + 'GET', + `/advertisers/${this.advertiserId}/creative-sets` + ); + } + + /** + * Create a new creative set + * @param data Creative set creation data + * @returns Created creative set + */ + async create(data: CreateCreativeSetInput): Promise> { + return this.adapter.request>( + 'POST', + `/advertisers/${this.advertiserId}/creative-sets`, + data + ); + } + + /** + * Add an asset to a creative set + * @param creativeSetId Creative set ID + * @param data Asset creation data + * @returns Created creative asset + */ + async addAsset( + creativeSetId: string, + data: CreateCreativeAssetInput + ): Promise> { + return this.adapter.request>( + 'POST', + `/advertisers/${this.advertiserId}/creative-sets/${validateResourceId(creativeSetId)}/assets`, + data + ); + } + + /** + * Remove an asset from a creative set + * @param creativeSetId Creative set ID + * @param assetId Asset ID to remove + */ + async removeAsset(creativeSetId: string, assetId: string): Promise { + await this.adapter.request( + 'DELETE', + `/advertisers/${this.advertiserId}/creative-sets/${validateResourceId(creativeSetId)}/assets/${validateResourceId(assetId)}` + ); + } +} diff --git a/src/resources/index.ts b/src/resources/index.ts new file mode 100644 index 0000000..d4f3c77 --- /dev/null +++ b/src/resources/index.ts @@ -0,0 +1,17 @@ +/** + * Resource exports + */ + +export { AdvertisersResource } from './advertisers'; +export { BuyerBrandsResource, BuyerLinkedBrandResource } from './brands'; +export { BrandBrandsResource } from './brand-brands'; +export { BundlesResource } from './bundles'; +export { BundleProductsResource } from './products'; +export { CampaignsResource } from './campaigns'; +export { ConversionEventsResource } from './conversion-events'; +export { CreativeSetsResource } from './creative-sets'; +export { MediaBuysResource } from './media-buys'; +export { PartnerHealthResource } from './partner-health'; +export { ReportingResource } from './reporting'; +export { SignalsResource } from './signals'; +export { TestCohortsResource } from './test-cohorts'; diff --git a/src/resources/media-buys.ts b/src/resources/media-buys.ts new file mode 100644 index 0000000..dbda81e --- /dev/null +++ b/src/resources/media-buys.ts @@ -0,0 +1,49 @@ +/** + * Media buys resource for managing advertiser media buy orders + * Scoped to a specific advertiser + */ + +import { type BaseAdapter, validateResourceId } from '../adapters/base'; +import type { MediaBuy, ListMediaBuysParams, PaginatedApiResponse, ApiResponse } from '../types'; + +/** + * Resource for managing media buys (scoped to an advertiser) + */ +export class MediaBuysResource { + constructor( + private readonly adapter: BaseAdapter, + private readonly advertiserId: string + ) {} + + /** + * List media buys for this advertiser + * @param params Pagination and filter parameters + * @returns Paginated list of media buys + */ + async list(params?: ListMediaBuysParams): Promise> { + return this.adapter.request>( + 'GET', + `/advertisers/${this.advertiserId}/media-buys`, + undefined, + { + params: { + take: params?.take, + skip: params?.skip, + campaignId: params?.campaignId, + }, + } + ); + } + + /** + * Get a media buy by ID + * @param mediaBuyId Media buy ID + * @returns Media buy details + */ + async get(mediaBuyId: string): Promise> { + return this.adapter.request>( + 'GET', + `/advertisers/${this.advertiserId}/media-buys/${validateResourceId(mediaBuyId)}` + ); + } +} diff --git a/src/resources/partner-health.ts b/src/resources/partner-health.ts new file mode 100644 index 0000000..6fc86c1 --- /dev/null +++ b/src/resources/partner-health.ts @@ -0,0 +1,22 @@ +/** + * Partner health resource for checking API health status + * For the Partner persona + */ + +import type { BaseAdapter } from '../adapters/base'; +import type { HealthCheckResponse, ApiResponse } from '../types'; + +/** + * Resource for checking API health (Partner persona) + */ +export class PartnerHealthResource { + constructor(private readonly adapter: BaseAdapter) {} + + /** + * Check the health of the API + * @returns Health check response with status, version, and timestamp + */ + async check(): Promise> { + return this.adapter.request>('GET', '/health'); + } +} diff --git a/src/resources/partner/agents.ts b/src/resources/partner/agents.ts deleted file mode 100644 index e7ca8f8..0000000 --- a/src/resources/partner/agents.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class AgentsResource { - constructor(private client: Scope3Client) {} - - /** - * Get agent - * Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the agent ID. - */ - async get( - params: operations['agent_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('agent_get', params); - } - - /** - * List agents - * List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - */ - async list( - params: operations['agent_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('agent_list', params); - } - - /** - * Register agent - * Register a new agent for media buying (SALES type) or outcome optimization (OUTCOME type). - */ - async register( - params: operations['agent_register']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('agent_register', params); - } - - /** - * Unregister agent - * Unregister an agent and disconnect it from the platform. Type is automatically inferred from the agent ID. - */ - async unregister( - params: operations['agent_unregister']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('agent_unregister', params); - } - - /** - * Update agent - * Update agent configuration and credentials. Type is automatically inferred from the agent ID. - */ - async update( - params: operations['agent_update']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('agent_update', params); - } -} diff --git a/src/resources/partner/channels.ts b/src/resources/partner/channels.ts deleted file mode 100644 index bb4e898..0000000 --- a/src/resources/partner/channels.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class ChannelsResource { - constructor(private client: Scope3Client) {} - - /** - * List channels - * List all available advertising channels and platforms. - */ - async list( - params: operations['channel_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('channel_list', params); - } -} diff --git a/src/resources/partner/creatives.ts b/src/resources/partner/creatives.ts deleted file mode 100644 index 1a53bcb..0000000 --- a/src/resources/partner/creatives.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class CreativesResource { - constructor(private client: Scope3Client) {} - - /** - * Sync creatives to sales agents - * Synchronize creatives to connected sales agents (DSPs, publisher platforms). - */ - async syncSalesAgents( - params: operations['creative_sync_sales_agents']['requestBody']['content']['application/json'] - ): Promise< - operations['creative_sync_sales_agents']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('creative_sync_sales_agents', params); - } -} diff --git a/src/resources/partner/customers.ts b/src/resources/partner/customers.ts deleted file mode 100644 index dd5175b..0000000 --- a/src/resources/partner/customers.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class CustomersResource { - constructor(private client: Scope3Client) {} - - /** - * Get customer info - * Get detailed information about a customer from the core database. - */ - async get( - params: operations['customer_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('customer_get', params); - } - - /** - * Get customer seats - * Get all seats associated with a customer from the core database. - */ - async getSeats( - params: operations['customer_get_seats']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('customer_get_seats', params); - } -} diff --git a/src/resources/partner/mediaBuys.ts b/src/resources/partner/mediaBuys.ts deleted file mode 100644 index a297a0d..0000000 --- a/src/resources/partner/mediaBuys.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class MediaBuysResource { - constructor(private client: Scope3Client) {} - - /** - * Create media buy - * Create a new media buy with budget, targeting, and creative specifications. - */ - async create( - params: operations['media_buy_create']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_buy_create', params); - } - - /** - * Update media buy - * Update an existing media buy with new budget, targeting, or creative assignments. - */ - async update( - params: operations['media_buy_update']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_buy_update', params); - } - - /** - * Delete media buy - * Delete a media buy and cancel any active placements. - */ - async delete( - params: operations['media_buy_delete']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_buy_delete', params); - } - - /** - * Execute media buy - * Execute a media buy, sending it to the configured sales agents for placement. - */ - async execute( - params: operations['media_buy_execute']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_buy_execute', params); - } - - /** - * Get media buy - * Get detailed information about a specific media buy. - */ - async get( - params: operations['media_buy_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_buy_get', params); - } - - /** - * List media buys - * List all media buys with optional filtering by brand agent, campaign, or status. - */ - async list( - params: operations['media_buy_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_buy_list', params); - } - - /** - * Validate media buy budget - * Validate a media buy budget against campaign constraints and available funds. - */ - async validateBudget( - params: operations['media_buy_validate_budget']['requestBody']['content']['application/json'] - ): Promise< - operations['media_buy_validate_budget']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('media_buy_validate_budget', params); - } -} diff --git a/src/resources/partner/mediaProducts.ts b/src/resources/partner/mediaProducts.ts deleted file mode 100644 index 203a001..0000000 --- a/src/resources/partner/mediaProducts.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class MediaProductsResource { - constructor(private client: Scope3Client) {} - - /** - * Discover media products - * Discover available media products from connected sales agents based on targeting criteria. - */ - async discover( - params: operations['media_product_discover']['requestBody']['content']['application/json'] - ): Promise< - operations['media_product_discover']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('media_product_discover', params); - } - - /** - * Save media product - * Save a discovered media product for future use in media buys. - */ - async save( - params: operations['media_product_save']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_product_save', params); - } - - /** - * List media products - * List saved media products with optional filtering. - */ - async list( - params: operations['media_product_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_product_list', params); - } - - /** - * Sync media products - * Synchronize media product catalog from connected sales agents. - */ - async sync( - params: operations['media_product_sync']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_product_sync', params); - } -} diff --git a/src/resources/partner/notifications.ts b/src/resources/partner/notifications.ts deleted file mode 100644 index d18bfd3..0000000 --- a/src/resources/partner/notifications.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class NotificationsResource { - constructor(private client: Scope3Client) {} - - /** - * List notifications - * List notifications for the authenticated user with optional filtering by status. - */ - async notificationsList( - params: operations['notifications_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('notifications_list', params); - } - - /** - * Mark notification as read - * Mark a specific notification as read. - */ - async notificationsMarkRead( - params: operations['notifications_mark_read']['requestBody']['content']['application/json'] - ): Promise< - operations['notifications_mark_read']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('notifications_mark_read', params); - } - - /** - * Mark notification as acknowledged - * Mark a specific notification as acknowledged. - */ - async notificationsMarkAcknowledged( - params: operations['notifications_mark_acknowledged']['requestBody']['content']['application/json'] - ): Promise< - operations['notifications_mark_acknowledged']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('notifications_mark_acknowledged', params); - } - - /** - * Mark all notifications as read - * Mark all notifications for the authenticated user as read. - */ - async notificationsMarkAllRead( - params: operations['notifications_mark_all_read']['requestBody']['content']['application/json'] - ): Promise< - operations['notifications_mark_all_read']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('notifications_mark_all_read', params); - } -} diff --git a/src/resources/partner/serviceTokens.ts b/src/resources/partner/serviceTokens.ts deleted file mode 100644 index 651de1b..0000000 --- a/src/resources/partner/serviceTokens.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class ServiceTokensResource { - constructor(private client: Scope3Client) {} - - /** - * Create service token - * Create a new service token for API authentication. Returns the full token which should be stored securely as it cannot be retrieved later. - */ - async create( - params: operations['service_token_create']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_create', params); - } - - /** - * List service tokens - * List all service tokens for the authenticated customer. Secrets are never returned, only metadata. - */ - async list( - params: operations['service_token_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_list', params); - } - - /** - * Get service token - * Get detailed information about a specific service token. The secret is never returned. - */ - async get( - params: operations['service_token_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_get', params); - } - - /** - * Update service token - * Update a service token. Only name, description, and expiration can be modified. - */ - async update( - params: operations['service_token_update']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_update', params); - } - - /** - * Archive service token - * Archive (soft delete) a service token. This immediately invalidates the token for authentication. - */ - async archive( - params: operations['service_token_archive']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_archive', params); - } -} diff --git a/src/resources/partner/tactics.ts b/src/resources/partner/tactics.ts deleted file mode 100644 index e5454ba..0000000 --- a/src/resources/partner/tactics.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class TacticsResource { - constructor(private client: Scope3Client) {} - - /** - * Create tactic - * Create a new tactic defining how to achieve campaign objectives. - */ - async create( - params: operations['tactic_create']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('tactic_create', params); - } - - /** - * Update tactic - * Update an existing tactic with new targeting, budget, or creative requirements. - */ - async update( - params: operations['tactic_update']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('tactic_update', params); - } - - /** - * Delete tactic - * Delete a tactic and all associated media buys. - */ - async delete( - params: operations['tactic_delete']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('tactic_delete', params); - } - - /** - * Get tactic - * Get detailed information about a specific tactic. - */ - async get( - params: operations['tactic_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('tactic_get', params); - } - - /** - * List tactics - * List all tactics with optional filtering by brand agent or campaign. - */ - async list( - params: operations['tactic_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('tactic_list', params); - } - - /** - * Link tactic to campaign - * Link a tactic to a campaign. - */ - async linkCampaign( - params: operations['tactic_link_campaign']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('tactic_link_campaign', params); - } - - /** - * Unlink tactic from campaign - * Unlink a tactic from a campaign. - */ - async unlinkCampaign( - params: operations['tactic_unlink_campaign']['requestBody']['content']['application/json'] - ): Promise< - operations['tactic_unlink_campaign']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('tactic_unlink_campaign', params); - } -} diff --git a/src/resources/partner/targeting.ts b/src/resources/partner/targeting.ts deleted file mode 100644 index 765baba..0000000 --- a/src/resources/partner/targeting.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class TargetingResource { - constructor(private client: Scope3Client) {} - - /** - * List countries - * Get all available countries for targeting. Use this to get valid country codes before creating brand agents. - */ - async countryList( - params: operations['country_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('country_list', params); - } - - /** - * List languages - * Get all available languages for targeting. Use this to get valid language codes before creating brand stories. - */ - async languageList( - params: operations['language_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('language_list', params); - } -} diff --git a/src/resources/partner/webhooks.ts b/src/resources/partner/webhooks.ts deleted file mode 100644 index e298327..0000000 --- a/src/resources/partner/webhooks.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/partner-api'; - -export class WebhooksResource { - constructor(private client: Scope3Client) {} - - /** - * Register webhook - * Register a webhook to receive real-time notifications about events. - */ - async register( - params: operations['webhook_register']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('webhook_register', params); - } - - /** - * List webhooks - * List all registered webhooks. - */ - async list( - params: operations['webhook_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('webhook_list', params); - } - - /** - * Delete webhook - * Delete a registered webhook. - */ - async delete( - params: operations['webhook_delete']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('webhook_delete', params); - } -} diff --git a/src/resources/platform/agents.ts b/src/resources/platform/agents.ts deleted file mode 100644 index f40255c..0000000 --- a/src/resources/platform/agents.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class AgentsResource { - constructor(private client: Scope3Client) {} - - /** - * Get agent - * Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the agent ID. - */ - async get( - params: operations['agent_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('agent_get', params); - } - - /** - * List agents - * List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - */ - async list( - params: operations['agent_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('agent_list', params); - } -} diff --git a/src/resources/platform/assets.ts b/src/resources/platform/assets.ts deleted file mode 100644 index f2a343b..0000000 --- a/src/resources/platform/assets.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class AssetsResource { - constructor(private client: Scope3Client) {} - - /** - * List assets - * List all uploaded assets with optional filtering by brand agent. - */ - async list( - params: operations['asset_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('asset_list', params); - } -} diff --git a/src/resources/platform/brandAgents.ts b/src/resources/platform/brandAgents.ts deleted file mode 100644 index 87ff2ad..0000000 --- a/src/resources/platform/brandAgents.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class BrandAgentsResource { - constructor(private client: Scope3Client) {} - - /** - * List brand agents - * List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. - */ - async list( - params: operations['brand_agent_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_agent_list', params); - } - - /** - * Get brand agent - * Get detailed information about a specific brand agent (advertiser account) by ID. - */ - async get( - params: operations['brand_agent_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_agent_get', params); - } - - /** - * Create brand agent - * Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. - */ - async create( - params: operations['brand_agent_create']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_agent_create', params); - } - - /** - * Update brand agent - * Update an existing brand agent with new information. - */ - async update( - params: operations['brand_agent_update']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_agent_update', params); - } - - /** - * Delete brand agent - * Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. - */ - async delete( - params: operations['brand_agent_delete']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_agent_delete', params); - } -} diff --git a/src/resources/platform/brandStandards.ts b/src/resources/platform/brandStandards.ts deleted file mode 100644 index 0c148d5..0000000 --- a/src/resources/platform/brandStandards.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class BrandStandardsResource { - constructor(private client: Scope3Client) {} - - /** - * Create brand standards - * Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand agent. - */ - async standardsCreate( - params: operations['brand_standards_create']['requestBody']['content']['application/json'] - ): Promise< - operations['brand_standards_create']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('brand_standards_create', params); - } - - /** - * Delete brand standards - * Delete brand standards for a brand agent. - */ - async standardsDelete( - params: operations['brand_standards_delete']['requestBody']['content']['application/json'] - ): Promise< - operations['brand_standards_delete']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('brand_standards_delete', params); - } - - /** - * List brand standards - * List all brand standards with optional filtering by brand agent. - */ - async standardsList( - params: operations['brand_standards_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_standards_list', params); - } -} diff --git a/src/resources/platform/brandStories.ts b/src/resources/platform/brandStories.ts deleted file mode 100644 index 7aca127..0000000 --- a/src/resources/platform/brandStories.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class BrandStoriesResource { - constructor(private client: Scope3Client) {} - - /** - * Create brand story - * Create a brand story containing the narrative, history, values, and key messaging for a brand agent. - */ - async storyCreate( - params: operations['brand_story_create']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_story_create', params); - } - - /** - * Update brand story - * Update an existing brand story with new information. - */ - async storyUpdate( - params: operations['brand_story_update']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_story_update', params); - } - - /** - * Delete brand story - * Delete a brand story. - */ - async storyDelete( - params: operations['brand_story_delete']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_story_delete', params); - } - - /** - * List brand stories - * List all brand stories with optional filtering by brand agent. - */ - async storyList( - params: operations['brand_story_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('brand_story_list', params); - } -} diff --git a/src/resources/platform/campaigns.ts b/src/resources/platform/campaigns.ts deleted file mode 100644 index 3fd7d88..0000000 --- a/src/resources/platform/campaigns.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class CampaignsResource { - constructor(private client: Scope3Client) {} - - /** - * List campaigns - * List all campaigns with optional filtering by brand agent. - */ - async list( - params: operations['campaign_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('campaign_list', params); - } - - /** - * Create campaign - * Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. - */ - async create( - params: operations['campaign_create']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('campaign_create', params); - } - - /** - * Get campaign - * Get detailed information about a specific campaign. - */ - async get( - params: operations['campaign_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('campaign_get', params); - } - - /** - * Update campaign - * Update an existing campaign with new information. - */ - async update( - params: operations['campaign_update']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('campaign_update', params); - } - - /** - * Delete campaign - * Delete a campaign and all associated resources. - */ - async delete( - params: operations['campaign_delete']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('campaign_delete', params); - } - - /** - * Get campaign summary - * Get a high-level summary of a campaign including key metrics and status. - */ - async getSummary( - params: operations['campaign_get_summary']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('campaign_get_summary', params); - } - - /** - * List campaign tactics - * List all tactics associated with a specific campaign. - */ - async listTactics( - params: operations['campaign_list_tactics']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('campaign_list_tactics', params); - } - - /** - * Validate campaign brief - * Validate a campaign brief to ensure it contains all necessary information for campaign creation. - */ - async validateBrief( - params: operations['campaign_validate_brief']['requestBody']['content']['application/json'] - ): Promise< - operations['campaign_validate_brief']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('campaign_validate_brief', params); - } -} diff --git a/src/resources/platform/channels.ts b/src/resources/platform/channels.ts deleted file mode 100644 index 965faae..0000000 --- a/src/resources/platform/channels.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class ChannelsResource { - constructor(private client: Scope3Client) {} - - /** - * List channels - * List all available advertising channels and platforms. - */ - async list( - params: operations['channel_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('channel_list', params); - } -} diff --git a/src/resources/platform/creatives.ts b/src/resources/platform/creatives.ts deleted file mode 100644 index 78b0622..0000000 --- a/src/resources/platform/creatives.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class CreativesResource { - constructor(private client: Scope3Client) {} - - /** - * Assign creative - * Assign a creative to a tactic or media buy. - */ - async assign( - params: operations['creative_assign']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('creative_assign', params); - } - - /** - * Create creative - * Create a new creative with assets, copy, and targeting specifications. - */ - async create( - params: operations['creative_create']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('creative_create', params); - } - - /** - * Update creative - * Update an existing creative with new assets, copy, or specifications. - */ - async update( - params: operations['creative_update']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('creative_update', params); - } - - /** - * Delete creative - * Delete a creative and remove it from any associated tactics or media buys. - */ - async delete( - params: operations['creative_delete']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('creative_delete', params); - } - - /** - * Get creative - * Get detailed information about a specific creative. - */ - async get( - params: operations['creative_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('creative_get', params); - } - - /** - * List creatives - * List all creatives with optional filtering by brand agent or campaign. - */ - async list( - params: operations['creative_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('creative_list', params); - } -} diff --git a/src/resources/platform/customers.ts b/src/resources/platform/customers.ts deleted file mode 100644 index 8ea46dd..0000000 --- a/src/resources/platform/customers.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class CustomersResource { - constructor(private client: Scope3Client) {} - - /** - * Get customer info - * Get detailed information about a customer from the core database. - */ - async get( - params: operations['customer_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('customer_get', params); - } - - /** - * Get customer seats - * Get all seats associated with a customer from the core database. - */ - async getSeats( - params: operations['customer_get_seats']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('customer_get_seats', params); - } -} diff --git a/src/resources/platform/mediaBuys.ts b/src/resources/platform/mediaBuys.ts deleted file mode 100644 index 14ed37d..0000000 --- a/src/resources/platform/mediaBuys.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class MediaBuysResource { - constructor(private client: Scope3Client) {} - - /** - * Get media buy - * Get detailed information about a specific media buy. - */ - async get( - params: operations['media_buy_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_buy_get', params); - } - - /** - * List media buys - * List all media buys with optional filtering by brand agent, campaign, or status. - */ - async list( - params: operations['media_buy_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_buy_list', params); - } -} diff --git a/src/resources/platform/mediaProducts.ts b/src/resources/platform/mediaProducts.ts deleted file mode 100644 index 2e8c517..0000000 --- a/src/resources/platform/mediaProducts.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class MediaProductsResource { - constructor(private client: Scope3Client) {} - - /** - * List media products - * List saved media products with optional filtering. - */ - async list( - params: operations['media_product_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('media_product_list', params); - } -} diff --git a/src/resources/platform/outcomeAgents.ts b/src/resources/platform/outcomeAgents.ts deleted file mode 100644 index 109e3b8..0000000 --- a/src/resources/platform/outcomeAgents.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class OutcomeAgentsResource { - constructor(private client: Scope3Client) {} - - /** - * Get proposals from outcome agents - * Request tactical proposals from outcome agents for a campaign. Outcome agents analyze the campaign brief and budget to propose execution strategies. - */ - async outcomesAgentGetProposals( - params: operations['outcomes_agent_get_proposals']['requestBody']['content']['application/json'] - ): Promise< - operations['outcomes_agent_get_proposals']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('outcomes_agent_get_proposals', params); - } - - /** - * Accept outcome agent proposal - * Accept a proposal from an outcome agent, creating a tactic and assigning it to the agent for management. - */ - async outcomesAgentAcceptProposal( - params: operations['outcomes_agent_accept_proposal']['requestBody']['content']['application/json'] - ): Promise< - operations['outcomes_agent_accept_proposal']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('outcomes_agent_accept_proposal', params); - } - - /** - * List tactics by outcome agent - * List all tactics managed by a specific outcome agent. - */ - async outcomesAgentListTactics( - params: operations['outcomes_agent_list_tactics']['requestBody']['content']['application/json'] - ): Promise< - operations['outcomes_agent_list_tactics']['responses'][200]['content']['application/json'] - > { - return this.client['callTool']('outcomes_agent_list_tactics', params); - } -} diff --git a/src/resources/platform/serviceTokens.ts b/src/resources/platform/serviceTokens.ts deleted file mode 100644 index a958299..0000000 --- a/src/resources/platform/serviceTokens.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class ServiceTokensResource { - constructor(private client: Scope3Client) {} - - /** - * Create service token - * Create a new service token for API authentication. Returns the full token which should be stored securely as it cannot be retrieved later. - */ - async create( - params: operations['service_token_create']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_create', params); - } - - /** - * List service tokens - * List all service tokens for the authenticated customer. Secrets are never returned, only metadata. - */ - async list( - params: operations['service_token_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_list', params); - } - - /** - * Get service token - * Get detailed information about a specific service token. The secret is never returned. - */ - async get( - params: operations['service_token_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_get', params); - } - - /** - * Update service token - * Update a service token. Only name, description, and expiration can be modified. - */ - async update( - params: operations['service_token_update']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_update', params); - } - - /** - * Archive service token - * Archive (soft delete) a service token. This immediately invalidates the token for authentication. - */ - async archive( - params: operations['service_token_archive']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('service_token_archive', params); - } -} diff --git a/src/resources/platform/tactics.ts b/src/resources/platform/tactics.ts deleted file mode 100644 index ee3ae4a..0000000 --- a/src/resources/platform/tactics.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class TacticsResource { - constructor(private client: Scope3Client) {} - - /** - * Get tactic - * Get detailed information about a specific tactic. - */ - async get( - params: operations['tactic_get']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('tactic_get', params); - } - - /** - * List tactics - * List all tactics with optional filtering by brand agent or campaign. - */ - async list( - params: operations['tactic_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('tactic_list', params); - } -} diff --git a/src/resources/platform/targeting.ts b/src/resources/platform/targeting.ts deleted file mode 100644 index d30cac3..0000000 --- a/src/resources/platform/targeting.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Scope3Client } from '../../client'; -import type { operations } from '../../types/platform-api'; - -export class TargetingResource { - constructor(private client: Scope3Client) {} - - /** - * List countries - * Get all available countries for targeting. Use this to get valid country codes before creating brand agents. - */ - async countryList( - params: operations['country_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('country_list', params); - } - - /** - * List languages - * Get all available languages for targeting. Use this to get valid language codes before creating brand stories. - */ - async languageList( - params: operations['language_list']['requestBody']['content']['application/json'] - ): Promise { - return this.client['callTool']('language_list', params); - } -} diff --git a/src/resources/products.ts b/src/resources/products.ts new file mode 100644 index 0000000..8a64f0e --- /dev/null +++ b/src/resources/products.ts @@ -0,0 +1,54 @@ +/** + * Bundle Products resource for managing products within a bundle + * Scoped to a specific bundle + */ + +import type { BaseAdapter } from '../adapters/base'; +import type { + BundleProductsResponse, + AddBundleProductsInput, + RemoveBundleProductsInput, + ApiResponse, +} from '../types'; + +/** + * Resource for managing products within a bundle + */ +export class BundleProductsResource { + constructor( + private readonly adapter: BaseAdapter, + private readonly bundleId: string + ) {} + + /** + * List all products in this bundle + * @returns Bundle products response with product list and budget context + */ + async list(): Promise> { + return this.adapter.request>( + 'GET', + `/bundles/${this.bundleId}/products` + ); + } + + /** + * Add products to this bundle + * @param data Products to add with selection details + * @returns Updated bundle products response + */ + async add(data: AddBundleProductsInput): Promise> { + return this.adapter.request>( + 'POST', + `/bundles/${this.bundleId}/products`, + data + ); + } + + /** + * Remove products from this bundle + * @param data Product IDs to remove + */ + async remove(data: RemoveBundleProductsInput): Promise { + await this.adapter.request('DELETE', `/bundles/${this.bundleId}/products`, data); + } +} diff --git a/src/resources/reporting.ts b/src/resources/reporting.ts new file mode 100644 index 0000000..2b5c83a --- /dev/null +++ b/src/resources/reporting.ts @@ -0,0 +1,39 @@ +/** + * Reporting resource for retrieving advertiser campaign metrics + * Scoped to a specific advertiser + */ + +import type { BaseAdapter } from '../adapters/base'; +import type { ReportingResponse, ReportingParams, ApiResponse } from '../types'; + +/** + * Resource for accessing reporting data (scoped to an advertiser) + */ +export class ReportingResource { + constructor( + private readonly adapter: BaseAdapter, + private readonly advertiserId: string + ) {} + + /** + * Get reporting metrics for this advertiser + * @param params Reporting filter parameters (days, date range, campaign, media buy) + * @returns Reporting response with daily metrics and totals + */ + async get(params?: ReportingParams): Promise> { + return this.adapter.request>( + 'GET', + `/advertisers/${this.advertiserId}/reporting`, + undefined, + { + params: { + days: params?.days, + startDate: params?.startDate, + endDate: params?.endDate, + campaignId: params?.campaignId, + mediaBuyId: params?.mediaBuyId, + }, + } + ); + } +} diff --git a/src/resources/signals.ts b/src/resources/signals.ts new file mode 100644 index 0000000..c0c9ddc --- /dev/null +++ b/src/resources/signals.ts @@ -0,0 +1,31 @@ +/** + * Signals resource for discovering and listing targeting signals + * Not scoped to a specific advertiser + */ + +import type { BaseAdapter } from '../adapters/base'; +import type { Signal, DiscoverSignalsInput, ApiResponse } from '../types'; + +/** + * Resource for managing signals + */ +export class SignalsResource { + constructor(private readonly adapter: BaseAdapter) {} + + /** + * Discover signals for campaign targeting + * @param data Optional filters for signal discovery + * @returns Discovered signals + */ + async discover(data?: DiscoverSignalsInput): Promise> { + return this.adapter.request>('POST', '/campaign/signals/discover', data); + } + + /** + * List all available signals + * @returns List of signals + */ + async list(): Promise> { + return this.adapter.request>('GET', '/signals'); + } +} diff --git a/src/resources/test-cohorts.ts b/src/resources/test-cohorts.ts new file mode 100644 index 0000000..8758a73 --- /dev/null +++ b/src/resources/test-cohorts.ts @@ -0,0 +1,41 @@ +/** + * Test cohorts resource for managing A/B test cohorts + * Scoped to a specific advertiser + */ + +import type { BaseAdapter } from '../adapters/base'; +import type { TestCohort, CreateTestCohortInput, ApiResponse } from '../types'; + +/** + * Resource for managing test cohorts (scoped to an advertiser) + */ +export class TestCohortsResource { + constructor( + private readonly adapter: BaseAdapter, + private readonly advertiserId: string + ) {} + + /** + * List all test cohorts for this advertiser + * @returns List of test cohorts + */ + async list(): Promise> { + return this.adapter.request>( + 'GET', + `/advertisers/${this.advertiserId}/test-cohorts` + ); + } + + /** + * Create a new test cohort + * @param data Test cohort creation data + * @returns Created test cohort + */ + async create(data: CreateTestCohortInput): Promise> { + return this.adapter.request>( + 'POST', + `/advertisers/${this.advertiserId}/test-cohorts`, + data + ); + } +} diff --git a/src/skill/bundled.ts b/src/skill/bundled.ts new file mode 100644 index 0000000..fc52d13 --- /dev/null +++ b/src/skill/bundled.ts @@ -0,0 +1,1590 @@ +/** + * Bundled skill.md content for each persona + * These are updated at build time by scripts/bundle-skill.ts + * Used as fallback when fetching from API fails + */ + +import type { Persona } from '../types'; + +export const bundledBuyerSkillMd = `--- +name: scope3-agentic-buyer +version: "2.0.0" +description: Scope3 Agentic Buyer API - AI-powered programmatic advertising +api_base_url: https://api.agentic.scope3.com/api/v2/buyer +auth: + type: bearer + header: Authorization + format: "Bearer {token}" + obtain_url: https://app.agentic.scope3.com/settings/api-keys +--- + +# Scope3 Agentic Buyer API + +This API enables AI-powered programmatic advertising with inventory discovery, campaign management, and creative orchestration. + +**Important**: This is a REST API accessed via the \`api_call\` tool. After reading this documentation, use \`api_call\` to make HTTP requests to the endpoints below. + +## โš ๏ธ CRITICAL: Exact Field Names Required + +**DO NOT GUESS FIELD NAMES.** Use these exact camelCase names: + +| Field | Type | Notes | +|-------|------|-------| +| \`advertiserId\` | string | NOT \`advertiser_id\` | +| \`flightDates\` | **object** | NOT \`startDate\`/\`endDate\` at root level | +| \`flightDates.startDate\` | string | ISO 8601: \`"2026-02-05T00:00:00Z"\` | +| \`flightDates.endDate\` | string | ISO 8601: \`"2026-02-10T23:59:59Z"\` | +| \`budget\` | **object** | NOT a number | +| \`budget.total\` | number | e.g., \`1000\` | +| \`budget.currency\` | string | \`"USD"\` (default) | +| \`constraints\` | object | Optional | +| \`constraints.channels\` | array | e.g., \`["display"]\`, \`["ctv"]\` | +| \`performanceConfig\` | object | Required for \`type: "performance"\` | + +## Quick Start + +1. **Use \`api_call\` tool**: All operations go through the generic \`api_call\` tool +2. **Base path**: All endpoints start with \`/api/v2/buyer/\` +3. **Authentication**: Handled automatically by the MCP session + +### Quick Campaign Creation (Minimal Fields) + +To create a discover campaign, these fields are **required**: + +\`\`\` +Step 1: Get your advertiser ID +GET /api/v2/advertisers +โ†’ Note the advertiser ID from the response + +Step 2: Create the campaign +POST /api/v2/campaigns +{ + "advertiserId": "", + "name": "My Campaign", + "flightDates": { + "startDate": "2026-02-05T00:00:00Z", + "endDate": "2026-02-10T23:59:59Z" + }, + "budget": { + "total": 1000, + "currency": "USD" + }, + "constraints": { + "channels": ["display"] + } +} +\`\`\` + +**CRITICAL - Use EXACT field names:** +- \`advertiserId\` (string) - NOT "advertiser_id" +- \`name\` (string) +- \`flightDates\` (object) - NOT "schedule", "dates", "startDate/endDate" at root + - \`flightDates.startDate\` (ISO 8601 datetime) + - \`flightDates.endDate\` (ISO 8601 datetime) +- \`budget\` (object) - NOT "totalBudget", "amount" + - \`budget.total\` (number) + - \`budget.currency\` (string, default "USD") +- \`constraints.channels\` (array) - e.g., \`["display"]\`, \`["ctv"]\`, \`["video"]\` + +**Note:** The campaign type defaults to \`bundle\`. Products can be added later via \`POST /api/v2/campaigns/{id}/products\`. + +**Important:** If the advertiser has a linked brand with a manifest URL, the system will automatically discover available products when the campaign is created. + +--- + +## Browsing Products Without a Campaign + +**When a user wants to browse products without mentioning a campaign:** + +Users may want to explore available inventory before committing to a campaign. Use \`POST /bundles/discover-products\` which: +- Creates a bundle automatically if no bundleId is provided +- Discovers products based on the advertiser's context +- Returns both the bundleId and discovered products + +**Interactive flow:** +1. **Browse products** - Call \`POST /bundles/discover-products\` with advertiser context + - Returns bundleId (auto-created if needed) and product groups + - Save the bundleId for later use +2. **Present products** - Show available inventory in a user-friendly way +3. **Add products to the bundle** - When the user likes products, add them via \`POST /bundles/{id}/products\` +4. **Create campaign later** - When ready, create a campaign with the bundleId via \`POST /campaigns/bundle\` + +**Example request:** +\`\`\`http +POST /api/v2/buyer/bundles/discover-products +{ + "advertiserId": "12345", + "channels": ["ctv", "display"], + "countries": ["US"], + "brief": "Looking for premium sports content", + "publisherDomain": "espn" +} +\`\`\` + +**Request Parameters (Filtering):** +- \`publisherDomain\` (optional): Filter products by publisher domain (exact domain component match). Example: "espn" matches "espn.com", "www.espn.com" but "esp" does not match + +**Example response:** +\`\`\`json +{ + "bundleId": "abc123-def456", + "productGroups": [...], + "totalGroups": 25, + "hasMoreGroups": true, + "summary": { "totalProducts": 150, "publishersCount": 25 } +} +\`\`\` + +**Key benefit:** Users can explore inventory without the overhead of creating bundles manually. The bundleId is returned so they can continue building their selection. + +--- + +## CRITICAL: Entity Hierarchy & Prerequisites + +Before creating campaigns, you MUST understand the entity hierarchy: + +\`\`\` +Customer (your account) + โ””โ”€โ”€ Advertiser (brand account - REQUIRED first) + โ”œโ”€โ”€ Campaigns (advertising campaigns) + โ”œโ”€โ”€ Creative Sets (ad creatives) + โ”œโ”€โ”€ Conversion Events (for performance tracking) + โ””โ”€โ”€ Test Cohorts (for A/B testing) +\`\`\` + +### Setup Checklist + +**Before you can run a campaign, you need:** + +1. **Advertiser** (REQUIRED) + - First, check if one exists: \`GET /api/v2/buyer/advertisers\` + - If not, create one: \`POST /api/v2/buyer/advertisers\` + - An advertiser represents a brand/company you're advertising for + +2. **Conversion Events** (REQUIRED for performance campaigns) + - Create tracking events: \`POST /api/v2/buyer/advertisers/{advertiserId}/conversion-events\` + - Configure what actions to optimize for (purchases, signups, etc.) + +3. **Creative Sets** (OPTIONAL) + - Create creative container: \`POST /api/v2/buyer/advertisers/{advertiserId}/creative-sets\` + - Add assets to it for ad delivery + +--- + +## Core Concepts + +| Concept | Description | Required For | +|---------|-------------|--------------| +| **Advertiser** | Top-level account representing a brand/company | Everything | +| **Campaign** | Advertising campaign with budget, dates, targeting | Running ads | +| **Creative Set** | Collection of creative assets | Ad delivery | +| **Conversion Event** | Trackable action (purchase, signup, etc.) | Performance campaigns | +| **Test Cohort** | A/B test configuration | Experimentation | +| **Media Buy** | Executed purchase record | Reporting | + +## Creating Campaigns + +There are **three campaign types**. When a user asks to create a campaign, present these options and let them choose: + +| Type | Description | When to Use | Status | +|------|-------------|-------------|--------| +| **Bundle** | Select specific products/inventory from a curated bundle | User wants control over specific inventory selections (premium placements, specific publishers) | โœ… Available | +| **Performance** | System auto-optimizes inventory based on objective | User wants system to optimize for business outcomes (ROAS, conversions, leads, sales) | โœ… Available | +| **Audience** | Target specific audience signals | User wants to target specific audience segments | โŒ Not yet implemented | + +**Recommended flow when user says "create a campaign":** +1. Ask: "What type of campaign would you like to create? You have three options: + - **Bundle**: You choose the specific ad inventory/products + - **Performance**: System automatically optimizes for your goal (ROAS, conversions, etc.) + - **Audience**: Target specific audience signals (not yet available)" +2. Based on their choice, follow the appropriate workflow below + +### Bundle Campaign Creation + +**When to use:** User wants control over which specific inventory/products to include. + +**Prerequisites:** Advertiser exists + +**CRITICAL: Interactive Flow Required** + +When a user asks to create a bundle campaign, follow this interactive flow: + +1. **Create the bundle** - Call \`POST /bundles\` with the user's parameters +2. **STOP and guide the user** - Do NOT immediately create the campaign. Instead: + - Explain that you've started building their campaign bundle + - Offer to show them available inventory: "Would you like me to show you the available inventory?" +3. **Discover products together** - Call \`GET /bundles/{id}/discover-products\` and present results + - Show product groups, publishers, channels, and price ranges in a user-friendly way +4. **Select products interactively** - Ask which products they want to add + - Call \`POST /bundles/{id}/products\` with their selections + - Show the updated bundle with selected products and budget allocation +5. **Confirm readiness** - "Your bundle has X products selected with $Y allocated. Ready to create the campaign?" +6. **Only then create the campaign** - Call \`POST /campaigns/bundle\` with the bundleId +7. **Launch** - Call \`POST /campaigns/{campaignId}/execute\` + +**Why this matters:** Bundles give users control over their inventory selection. Skipping product discovery means they lose that control. + +**IMPORTANT:** Do NOT expose API details to the user. Communicate conversationally about campaigns, inventory, products, and budgetsโ€”not about endpoints or HTTP methods. + +See "Workflow 2: Bundle-First Campaign Creation" below for detailed request/response examples. + +### Performance Campaign Creation + +**When to use:** User wants system to optimize for business outcomes automatically. + +**Prerequisites:** Advertiser exists + Conversion events configured + +**Required field:** \`performanceConfig.objective\` (one of: ROAS, CONVERSIONS, LEADS, SALES) + +**Steps:** +1. Verify advertiser: \`GET /advertisers\` +2. Check conversion events: \`GET /advertisers/{id}/conversion-events\` +3. Create campaign: \`POST /campaigns/performance\` +4. Launch: \`POST /campaigns/{campaignId}/execute\` + +See "Workflow 3: Create a Performance Campaign" below for detailed request/response examples. + +### Audience Campaign Creation + +**Status:** โŒ Not yet implemented - returns 501 Not Implemented + +--- + +## Complete Workflows + +### Workflow 1: First-Time Setup + +If you're starting fresh with a new advertiser, follow these steps. + +\`\`\` +Step 1: Check if an advertiser already exists +GET /api/v2/buyer/advertisers +โ†’ If advertisers exist, you can use one. If not, create one (see Create Advertiser below). + +Step 2: Create conversion events (for performance campaigns) +POST /api/v2/buyer/advertisers/{advertiserId}/conversion-events +{ + "name": "Purchase", + "type": "PURCHASE", + "description": "Completed purchase event" +} + +Step 3: Now you can discover products and create campaigns! +\`\`\` + +--- + +### Workflow 2: Bundle-First Campaign Creation + +This workflow allows you to create a product bundle before committing to a campaign. The bundle acts as a collection of selected products. + +\`\`\` +Step 1: Create an empty bundle +POST /api/v2/buyer/bundles +{ + "advertiserId": "12345", + "channels": ["ctv", "display"], + "countries": ["US", "CA"], + "brief": "Premium video inventory for tech enthusiasts", + "budget": 50000, + "flightDates": { + "startDate": "2025-02-01T00:00:00Z", + "endDate": "2025-03-31T23:59:59Z" + } +} +โ†’ Returns bundleId only +โ†’ Save the bundleId for the next steps! + +Step 2: Discover available products for the bundle +GET /api/v2/buyer/bundles/{bundleId}/discover-products +โ†’ Returns productGroups +โ†’ Review products and note which to add + +Step 3: Add selected products to the bundle +POST /api/v2/buyer/bundles/{bundleId}/products +{ + "products": [ + { + "productId": "product_123", + "salesAgentId": "agent_456", + "groupId": "ctx_123-group-0", + "groupName": "Publisher Name", + "cpm": 12.50, + "budget": 5000 + } + ] +} +โ†’ Adds products to the bundle selection +โ†’ Only selected products will be used when creating a campaign + +Step 4: Create campaign with the bundle +POST /api/v2/buyer/campaigns/bundle +{ + "advertiserId": "12345", + "name": "Q1 2025 CTV Campaign", + "bundleId": "abc123-def456-ghi789", + "flightDates": { + "startDate": "2025-02-01T00:00:00Z", + "endDate": "2025-03-31T23:59:59Z" + }, + "budget": { + "total": 50000, + "currency": "USD", + "pacing": "EVEN" + } +} +โ†’ bundleId (required) attaches the bundle to the campaign +โ†’ Campaign uses products that were selected in Step 3 + +Step 5: Launch the campaign +POST /api/v2/buyer/campaigns/{campaignId}/execute +โ†’ Activates the campaign +\`\`\` + +**Bundle Product Management:** +- \`GET /bundles/{id}/products\` - List selected products in the bundle +- \`POST /bundles/{id}/products\` - Add products to the bundle +- \`DELETE /bundles/{id}/products\` - Remove products from the bundle + +**Key Points:** +- Create bundle โ†’ Discover products โ†’ Select products โ†’ Create campaign โ†’ Execute +- Products must be added to the bundle BEFORE creating the campaign +- Only products selected via \`POST /bundles/{id}/products\` are used +- The bundle stores the product selection until you create a campaign + +### Bundle Lifecycle + +**How long do bundles live?** +- Bundles persist indefinitely until explicitly completed +- There is no automatic expiration or TTL +- Bundles remain in "active" status until a campaign is executed + +**Can bundles be reused?** +- Yes, the same bundleId can be attached to multiple campaigns +- Each campaign independently references the bundle's products +- Modifying the bundle affects all campaigns that reference it + +**What happens after campaign creation?** +- The bundle remains active after campaign creation +- You can continue adding/removing products from the bundle +- The bundle is only "completed" when the campaign is executed +- Once completed, the bundle cannot be modified + +**Best Practices:** +- Create one bundle per campaign workflow +- Complete product selection before creating the campaign +- Don't reuse bundles across unrelated campaigns + +### Workflow 3: Create a Performance Campaign + +Performance campaigns optimize for specific business outcomes (ROAS, conversions, etc.). The system handles inventory selection automatically based on your objectives and constraints. + +**Key Difference from Bundle Campaigns:** Performance campaigns do NOT require manual product or signal selection - you define the objective and the system optimizes automatically. + +**Prerequisites:** +- Advertiser exists +- Conversion events configured (tells system what to optimize for) + +\`\`\` +Step 1: Verify advertiser exists (filter by status and name) +GET /api/v2/buyer/advertisers?status=ACTIVE&name={advertiserName} + +Step 2: Check/create conversion events +GET /api/v2/buyer/advertisers/{advertiserId}/conversion-events +# If empty, create one: +POST /api/v2/buyer/advertisers/{advertiserId}/conversion-events +{ + "name": "Purchase", + "type": "PURCHASE" +} + +Step 3: Create performance campaign with objective and constraints +POST /api/v2/buyer/campaigns/performance +{ + "advertiserId": "12345", + "name": "Q1 ROAS Optimization", + "flightDates": { + "startDate": "2025-02-01T00:00:00Z", + "endDate": "2025-03-31T23:59:59Z" + }, + "budget": { + "total": 100000, + "currency": "USD" + }, + "performanceConfig": { + "objective": "ROAS", + "goals": { + "targetRoas": 4.0 + } + }, + "constraints": { + "channels": ["ctv", "display"], + "countries": ["US"] + } +} +โ†’ performanceConfig.objective is required + +Step 4: Launch +POST /api/v2/buyer/campaigns/{campaignId}/execute +\`\`\` + +### Workflow 4: Create an Audience Campaign + +**NOTE**: Audience campaigns are not yet implemented and will return 501 Not Implemented. + +Audience campaigns will target specific audience signals once implemented. + +\`\`\` +Step 1: Discover available signals +POST /api/v2/buyer/campaign/signals/discover +{ + "filters": { + "catalogTypes": ["marketplace"] + } +} +โ†’ Returns signals available for targeting + +Step 2: Create audience campaign with selected signals (NOT YET IMPLEMENTED) +POST /api/v2/buyer/campaigns/audience +{ + "advertiserId": "12345", + "name": "Tech Enthusiasts Campaign", + "flightDates": { + "startDate": "2025-02-01T00:00:00Z", + "endDate": "2025-03-31T23:59:59Z" + }, + "budget": { + "total": 25000, + "currency": "USD" + }, + "signals": ["tech_enthusiasts_signal_id", "early_adopters_signal_id"] +} +โ†’ Returns 501 Not Implemented + +Step 3: Launch (once audience campaigns are implemented) +POST /api/v2/buyer/campaigns/{campaignId}/execute +\`\`\` + +--- + +## API Endpoints Reference + +### Advertisers + +#### List Advertisers +\`\`\`http +GET /api/v2/buyer/advertisers?status=ACTIVE&name=Acme&take=50&skip=0 +\`\`\` + +**Query Parameters (Filters):** +- \`status\` (optional): Filter by status - \`ACTIVE\` or \`ARCHIVED\` +- \`name\` (optional): Filter by name (case-insensitive, partial match). Example: \`name=Acme\` matches "Acme Corp", "acme inc", etc. +- \`take\` (optional): Results per page (default: 50, max: 250) +- \`skip\` (optional): Pagination offset (default: 0) + +#### Create Advertiser + +**โš ๏ธ IMPORTANT: Follow this interactive flow before calling this endpoint.** + +When a user asks to create an advertiser, **DO NOT immediately call the API**: + +1. **Ask for the name** - "What would you like to name your advertiser?" +2. **Check for existing brands** - Call \`GET /api/v2/buyer/brands\` +3. **Offer to link a brand** - If brands exist, ask: "Would you like to link one of these brands? Linking enables product discovery." +4. **Create the advertiser** with the user's chosen name +5. **Link the brand** if selected via \`PUT /api/v2/buyer/advertisers/{id}/brand\` + +โš ๏ธ Without a linked brand, the advertiser cannot discover products or create bundle campaigns. + +\`\`\`http +POST /api/v2/buyer/advertisers +{ + "name": "Acme Corp", + "description": "Global advertising account" +} +\`\`\` + +#### Update Advertiser +\`\`\`http +PUT /api/v2/buyer/advertisers/{id} +{ + "name": "Acme Corporation", + "description": "Updated description" +} +\`\`\` + +--- + +### Brands + +Brands exist at the customer level and can be linked to advertisers. + +#### List Brands +\`\`\`http +GET /api/v2/buyer/brands?status=ACTIVE&name=Acme&take=50&skip=0 +\`\`\` + +**Query Parameters (Filters):** +- \`status\` (optional): Filter by status - \`ACTIVE\` or \`ARCHIVED\` +- \`name\` (optional): Filter by name (case-insensitive, partial match). Example: \`name=Acme\` matches "Acme Brand", "acme inc", etc. +- \`take\` (optional): Results per page (default: 50, max: 250) +- \`skip\` (optional): Pagination offset (default: 0) + +#### Get Linked Brand +Get the brand linked to an advertiser. +\`\`\`http +GET /api/v2/buyer/advertisers/{advertiserId}/brand +\`\`\` + +#### Link Brand to Advertiser +Link a brand to an advertiser. Brands must be created first via the Brand API. +\`\`\`http +PUT /api/v2/buyer/advertisers/{advertiserId}/brand +{ + "brandId": "brand_123" +} +\`\`\` + +**Notes:** +- An advertiser can only have one linked brand at a time +- To change the brand, unlink the current one first + +#### Unlink Brand from Advertiser +Remove the brand link from an advertiser. +\`\`\`http +DELETE /api/v2/buyer/advertisers/{advertiserId}/brand +\`\`\` + +--- + +### Campaigns + +The API supports three campaign types with **type-specific endpoints**: + +| Type | Create Endpoint | Update Endpoint | Prerequisites | +|------|-----------------|-----------------|---------------| +| \`bundle\` | \`POST /campaigns/bundle\` | \`PUT /campaigns/bundle/{id}\` | Advertiser + **bundleId (required)** | +| \`performance\` | \`POST /campaigns/performance\` | \`PUT /campaigns/performance/{id}\` | Advertiser + performanceConfig.objective | +| \`audience\` | \`POST /campaigns/audience\` | \`PUT /campaigns/audience/{id}\` | **Not implemented (501)** | + +**IMPORTANT**: Each campaign type has its own create and update endpoints. You cannot create a campaign at the generic \`/campaigns\` endpoint. + +**IMPORTANT for Bundle campaigns**: +- **REQUIRED**: Call \`POST /bundles\` first to get a \`bundleId\`, then create campaign with that bundle +- You cannot create a bundle campaign without a bundleId + +**Performance campaigns**: Require \`performanceConfig.objective\` (ROAS, CONVERSIONS, LEADS, or SALES). + +**Audience campaigns**: Not yet implemented - will return 501 Not Implemented. + +--- + +#### Create Bundle (Pre-Campaign) + +Creates an empty bundle. Product discovery is done separately via GET /bundles/{id}/discover-products. + +\`\`\`http +POST /api/v2/buyer/bundles +{ + "advertiserId": "12345", + "channels": ["ctv", "display"], + "countries": ["US", "CA"], + "brief": "Premium video inventory for tech enthusiasts", + "budget": 50000, + "flightDates": { + "startDate": "2025-02-01T00:00:00Z", + "endDate": "2025-03-31T23:59:59Z" + } +} +\`\`\` + +**Request Parameters:** +- \`advertiserId\` (required): Advertiser ID to resolve brand manifest +- \`channels\` (optional): Channels to search (defaults to ["display", "olv", "ctv"]) +- \`countries\` (optional): Target countries (defaults to brand agent countries) +- \`brief\` (optional): Natural language context for product search +- \`flightDates\` (optional): Flight dates for availability filtering +- \`budget\` (optional): Budget for budget context + +**Response:** +\`\`\`json +{ + "bundleId": "abc123-def456-ghi789" +} +\`\`\` + +**Important:** Save the \`bundleId\` to discover products and add them to the bundle. + +--- + +#### Discover Products for Bundle + +Discovers available products for an existing bundle. + +\`\`\`http +GET /api/v2/buyer/bundles/{bundleId}/discover-products?groupLimit=10&groupOffset=0&productsPerGroup=5&publisherDomain=hulu +\`\`\` + +**Path Parameters:** +- \`bundleId\` (required): Bundle ID from POST /bundles + +**Query Parameters (Pagination):** +- \`groupLimit\` (optional): Maximum number of product groups to return (default: 10, max: 50) +- \`groupOffset\` (optional): Number of groups to skip for pagination (default: 0) +- \`productsPerGroup\` (optional): Maximum products to return per group (default: 5, max: 50). Increase this to see more products in each group when \`hasMoreProducts\` is true. + +**Query Parameters (Filtering):** +- \`publisherDomain\` (optional): Filter products by publisher domain (exact domain component match). Example: "hulu" matches "hulu.com", "www.hulu.com", "hulu.tv" but "hul" does not match + +**Response:** +\`\`\`json +{ + "bundleId": "abc123-def456-ghi789", + "productGroups": [ + { + "groupId": "group-0", + "groupName": "Publisher Name", + "products": [ + { + "productId": "product_123", + "name": "Premium CTV Inventory", + "publisher": "example.com", + "channel": "ctv", + "cpm": 12.50, + "salesAgentId": "agent_456" + } + ], + "productCount": 5 + } + ], + "totalGroups": 25, + "hasMoreGroups": true, + "summary": { + "totalProducts": 150, + "publishersCount": 25, + "priceRange": { "min": 5.0, "max": 25.0, "avg": 12.5 } + }, + "budgetContext": { + "sessionBudget": 50000, + "allocatedBudget": 0, + "remainingBudget": 50000 + } +} +\`\`\` + +**Pagination Notes:** +- \`totalGroups\`: Total number of product groups available +- \`hasMoreGroups\`: If true, use \`groupOffset\` to fetch more groups +- \`productCount\`: Number of products in each group (controlled by \`productsPerGroup\` parameter) + +**Pagination Example:** + +To paginate through all product groups: +\`\`\` +# Page 1 - First 10 groups +GET /api/v2/buyer/bundles/{bundleId}/discover-products?groupLimit=10&groupOffset=0 + +# Page 2 - Next 10 groups +GET /api/v2/buyer/bundles/{bundleId}/discover-products?groupLimit=10&groupOffset=10 + +# Continue until hasMoreGroups is false +\`\`\` + +To see more products within a group, increase \`productsPerGroup\`: +\`\`\` +# Show up to 20 products per group +GET /api/v2/buyer/bundles/{bundleId}/discover-products?productsPerGroup=20 +\`\`\` + +--- + +#### Add Products to Bundle + +Adds products to a bundle. Products must have been discovered via \`GET /bundles/{id}/discover-products\` first. + +\`\`\`http +POST /api/v2/buyer/bundles/{bundleId}/products +{ + "products": [ + { + "productId": "product_123", + "salesAgentId": "agent_456", + "groupId": "ctx_123-group-0", + "groupName": "Publisher Name", + "cpm": 12.50, + "budget": 5000 + } + ] +} +\`\`\` + +**Path Parameters:** +- \`bundleId\` (required): Bundle ID + +**Request Body:** +- \`products\` (required): Array of products to add + - \`productId\` (required): Product ID from discover-products + - \`salesAgentId\` (required): Sales agent ID from the product + - \`groupId\` (required): Group ID where the product was discovered + - \`groupName\` (required): Name of the group + - \`cpm\` (optional): CPM for the product + - \`budget\` (optional): Budget allocation for this product + +**Response:** +\`\`\`json +{ + "bundleId": "abc123-def456-ghi789", + "products": [ + { + "productId": "product_123", + "salesAgentId": "agent_456", + "cpm": 12.50, + "budget": 5000, + "selectedAt": "2025-02-01T10:00:00Z", + "groupId": "ctx_123-group-0", + "groupName": "Publisher Name" + } + ], + "totalProducts": 1, + "budgetContext": { + "sessionBudget": 50000, + "allocatedBudget": 5000, + "remainingBudget": 45000 + } +} +\`\`\` + +--- + +#### Get Bundle Products + +Gets the list of products selected for a bundle. + +\`\`\`http +GET /api/v2/buyer/bundles/{bundleId}/products +\`\`\` + +**Path Parameters:** +- \`bundleId\` (required): Bundle ID + +**Response:** Same format as Add Products response. + +--- + +#### Remove Products from Bundle + +Removes products from a bundle. + +\`\`\`http +DELETE /api/v2/buyer/bundles/{bundleId}/products +{ + "productIds": ["product_123", "product_456"] +} +\`\`\` + +**Path Parameters:** +- \`bundleId\` (required): Bundle ID + +**Request Body:** +- \`productIds\` (required): Array of product IDs to remove + +**Response:** Same format as Add Products response (with updated products list). + +--- + +#### List Campaigns +\`\`\`http +GET /api/v2/buyer/campaigns?advertiserId=12345&type=bundle&status=ACTIVE +\`\`\` + +**Query Parameters:** +- \`advertiserId\` (optional): Filter by advertiser +- \`type\` (optional): \`bundle\`, \`audience\`, or \`performance\` +- \`status\` (optional): \`DRAFT\`, \`ACTIVE\`, \`PAUSED\`, \`COMPLETED\`, \`ARCHIVED\` + +#### Get Campaign +\`\`\`http +GET /api/v2/buyer/campaigns/{campaignId} +\`\`\` + +#### Create Bundle Campaign +\`\`\`http +POST /api/v2/buyer/campaigns/bundle +{ + "advertiserId": "12345", + "name": "Q1 CTV Bundle", + "bundleId": "abc123-def456-ghi789", + "productIds": ["prod_123", "prod_456"], + "flightDates": { + "startDate": "2025-02-01T00:00:00Z", + "endDate": "2025-03-31T23:59:59Z" + }, + "budget": { + "total": 50000, + "currency": "USD" + }, + "brief": "Optional campaign brief" +} +\`\`\` + +**Required fields:** +- \`advertiserId\`: Advertiser ID +- \`name\`: Campaign name (1-255 chars) +- \`bundleId\`: Bundle ID from \`POST /bundles\` **(required)** +- \`flightDates\`: Start and end dates +- \`budget\`: Total and currency + +**Optional fields:** +- \`productIds\`: Product IDs to pre-select from the bundle +- \`constraints.channels\`: Target channels (ctv, display, olv, audio) +- \`constraints.countries\`: Target countries (ISO 3166-1 alpha-2 codes) +- \`brief\`: Campaign brief + +#### Update Bundle Campaign +\`\`\`http +PUT /api/v2/buyer/campaigns/bundle/{campaignId} +{ + "name": "Updated Campaign Name", + "budget": { + "total": 75000 + }, + "productIds": ["prod_789"] +} +\`\`\` +All fields are optional. Campaign must be of type "bundle". + +--- + +#### Create Performance Campaign +\`\`\`http +POST /api/v2/buyer/campaigns/performance +{ + "advertiserId": "12345", + "name": "Q1 ROAS Campaign", + "flightDates": { + "startDate": "2025-02-01T00:00:00Z", + "endDate": "2025-03-31T23:59:59Z" + }, + "budget": { + "total": 100000, + "currency": "USD" + }, + "performanceConfig": { + "objective": "ROAS", + "goals": { + "targetRoas": 4.0 + } + }, + "constraints": { + "channels": ["ctv", "display"], + "countries": ["US"] + } +} +\`\`\` + +**Required fields:** +- \`advertiserId\`: Advertiser ID +- \`name\`: Campaign name (1-255 chars) +- \`flightDates\`: Start and end dates +- \`budget\`: Total and currency +- \`performanceConfig.objective\`: One of \`ROAS\`, \`CONVERSIONS\`, \`LEADS\`, \`SALES\` + +#### Update Performance Campaign +\`\`\`http +PUT /api/v2/buyer/campaigns/performance/{campaignId} +{ + "name": "Updated Campaign Name", + "performanceConfig": { + "goals": { + "targetRoas": 5.0 + } + } +} +\`\`\` +All fields are optional. Campaign must be of type "performance". + +--- + +#### Create Audience Campaign (Not Implemented) +\`\`\`http +POST /api/v2/buyer/campaigns/audience +\`\`\` +**Returns 501 Not Implemented** - Audience campaigns are not yet available. + +#### Update Audience Campaign (Not Implemented) +\`\`\`http +PUT /api/v2/buyer/campaigns/audience/{campaignId} +\`\`\` +**Returns 501 Not Implemented** - Audience campaigns are not yet available. + +#### Execute Campaign (Launch) +\`\`\`http +POST /api/v2/buyer/campaigns/{campaignId}/execute +\`\`\` +Transitions campaign from DRAFT to ACTIVE. + +#### Pause Campaign +\`\`\`http +POST /api/v2/buyer/campaigns/{campaignId}/pause +\`\`\` + +--- + +### Conversion Events + +Required for performance campaigns to track and optimize conversions. + +#### List Conversion Events +\`\`\`http +GET /api/v2/buyer/advertisers/{advertiserId}/conversion-events +\`\`\` + +#### Create Conversion Event +\`\`\`http +POST /api/v2/buyer/advertisers/{advertiserId}/conversion-events +{ + "name": "Purchase", + "type": "PURCHASE", + "description": "Completed purchase event", + "value": 100, + "currency": "USD" +} +\`\`\` + +**Event Types:** \`PURCHASE\`, \`SIGNUP\`, \`LEAD\`, \`PAGE_VIEW\`, \`ADD_TO_CART\`, \`CUSTOM\` + +#### Get Conversion Event +\`\`\`http +GET /api/v2/buyer/advertisers/{advertiserId}/conversion-events/{id} +\`\`\` + +#### Update Conversion Event +\`\`\`http +PUT /api/v2/buyer/advertisers/{advertiserId}/conversion-events/{id} +{ + "name": "High-Value Purchase", + "value": 200 +} +\`\`\` + +--- + +### Test Cohorts + +For A/B testing campaign variations. + +#### List Test Cohorts +\`\`\`http +GET /api/v2/buyer/advertisers/{advertiserId}/test-cohorts +\`\`\` + +#### Create Test Cohort +\`\`\`http +POST /api/v2/buyer/advertisers/{advertiserId}/test-cohorts +{ + "name": "Q1 Creative Test", + "description": "Testing new vs old creatives", + "splitPercentage": 50 +} +\`\`\` + +--- + +### Creative Sets + +#### List Creative Sets +\`\`\`http +GET /api/v2/buyer/advertisers/{advertiserId}/creative-sets +\`\`\` + +#### Create Creative Set +\`\`\`http +POST /api/v2/buyer/advertisers/{advertiserId}/creative-sets +{ + "name": "Q1 Video Creatives", + "type": "video" +} +\`\`\` + +#### Add Asset to Creative Set +\`\`\`http +POST /api/v2/buyer/advertisers/{advertiserId}/creative-sets/{creativeSetId}/assets +{ + "assetUrl": "https://example.com/video.mp4", + "name": "Hero Video 30s", + "type": "video", + "duration": 30 +} +\`\`\` + +#### Remove Asset +\`\`\`http +DELETE /api/v2/buyer/advertisers/{advertiserId}/creative-sets/{creativeSetId}/assets/{assetId} +\`\`\` + +--- + +### Reporting + +#### Get Reporting +\`\`\`http +GET /api/v2/buyer/advertisers/{advertiserId}/reporting?days=7 +\`\`\` + +**Query Parameters:** +- \`days\` (optional): Number of days to include (default: 7, max: 90) +- \`startDate\` (optional): Start date in ISO format (YYYY-MM-DD) +- \`endDate\` (optional): End date in ISO format (YYYY-MM-DD) +- \`campaignId\` (optional): Filter by campaign ID +- \`mediaBuyId\` (optional): Filter by media buy ID + +**Response:** \`{ dailyMetrics: [{ date, impressions, clicks, spend }], totals: { impressions, clicks, spend }, periodStart, periodEnd }\` + +--- + +### Media Buys + +View executed purchases. + +#### List Media Buys +\`\`\`http +GET /api/v2/buyer/advertisers/{advertiserId}/media-buys?campaignId=cmp_123 +\`\`\` + +#### Get Media Buy +\`\`\`http +GET /api/v2/buyer/advertisers/{advertiserId}/media-buys/{mediaBuyId} +\`\`\` + +--- + +### Signals (for Audience Campaigns) + +#### Discover Signals +\`\`\`http +POST /api/v2/buyer/campaign/signals/discover +\`\`\` + +Discover available signals before creating a campaign. See "Discover Signals (Pre-Campaign)" above for details. + +#### List Saved Signals +\`\`\`http +GET /api/v2/buyer/signals +\`\`\` + +Returns signals that have been saved to your account. + +--- + +## Error Handling + +All errors follow this format: +\`\`\`json +{ + "data": null, + "error": { + "code": "VALIDATION_ERROR", + "message": "Human-readable message", + "details": {} + } +} +\`\`\` + +| Code | HTTP Status | Resolution | +|------|-------------|------------| +| \`VALIDATION_ERROR\` | 400 | Check request body against schema | +| \`UNAUTHORIZED\` | 401 | Verify API key/auth | +| \`ACCESS_DENIED\` | 403 | Check permissions | +| \`NOT_FOUND\` | 404 | Verify resource ID exists | +| \`CONFLICT\` | 409 | Resource already exists (e.g., brand) | +| \`RATE_LIMITED\` | 429 | Wait and retry | + +--- + +## Common Mistakes to Avoid + +1. **Creating campaign without advertiser** - Always create/verify advertiser first +2. **Bundle campaign without bundleId** - You MUST call \`POST /bundles\` first and use the returned \`bundleId\` when creating the campaign +3. **Creating campaign without adding products** - You MUST add products to the bundle via \`POST /bundles/{id}/products\` BEFORE creating the campaign +4. **Expecting products from POST /bundles** - POST /bundles only returns bundleId; call \`GET /bundles/{id}/discover-products\` to get product suggestions +5. **Performance campaign without conversion events** - System needs events to optimize +6. **Adding products/signals to performance campaigns** - Performance campaigns don't need them; the system handles inventory selection automatically based on your objective +7. **Forgetting to execute** - Campaigns start in DRAFT status, must call \`/execute\` +8. **Wrong endpoint path** - Always use \`/api/v2/buyer/\` prefix +9. **Calling execute without products** - Must add products to the bundle before executing +`; + +export const bundledBrandSkillMd = `--- +name: scope3-agentic-brand +version: "2.0.0" +description: Scope3 Agentic Brand API - Brand identity and manifest management +api_base_url: https://api.agentic.scope3.com/api/v2/brand +auth: + type: bearer + header: Authorization + format: "Bearer {token}" + obtain_url: https://app.agentic.scope3.com/settings/api-keys +--- + +# Scope3 Agentic Brand API + +This API enables management of brand identity and manifests for AI-powered programmatic advertising. + +**Important**: This is a REST API accessed via the \`api_call\` tool. After reading this documentation, use \`api_call\` to make HTTP requests to the endpoints below. + +## Quick Start + +1. **Use \`api_call\` tool**: All operations go through the generic \`api_call\` tool +2. **Base path**: All endpoints start with \`/api/v2/brand/\` +3. **Authentication**: Handled automatically by the MCP session + +--- + +## Core Concepts + +### What is a Brand? + +A **Brand** represents the identity of a company or product for advertising purposes. Brands exist at the **customer level** - they are NOT nested under advertisers. + +### Brand Manifest + +A brand manifest is a JSON document (conforming to ADCP v2) that describes everything about a brand's identity: +- **Name and URL** - Brand name and website +- **Logos** - Logo images with tags and dimensions +- **Colors** - Primary, secondary, accent, background, and text colors +- **Fonts** - Typography choices and font file URLs +- **Tone** - Voice and communication style +- **Tagline** - Brand slogan +- **Assets** - Images, videos, audio files +- **Product Catalog** - Product feed configuration +- **Disclaimers** - Legal text requirements +- **Contact** - Contact information + +### Entity Hierarchy + +\`\`\` +Customer (your account) + โ”œโ”€โ”€ Brands (at customer level) + โ”‚ โ””โ”€โ”€ Brand identity configuration (manifest) + โ”‚ + โ””โ”€โ”€ Advertisers + โ”œโ”€โ”€ Campaigns + โ”œโ”€โ”€ Creative Sets + โ””โ”€โ”€ Conversion Events +\`\`\` + +--- + +## Endpoints Reference + +### List Brands + +List all brands for the current customer. + +\`\`\` +GET /api/v2/brand/brands +\`\`\` + +**Query Parameters:** +| Parameter | Type | Description | +|-----------|------|-------------| +| \`take\` | number | Number of results to return (max 250, default 50) | +| \`skip\` | number | Number of results to skip for pagination | + +**Response:** +\`\`\`json +{ + "data": [ + { + "id": "brand_123", + "name": "Acme Corp", + "manifestUrl": "https://storage.googleapis.com/...", + "createdAt": "2025-01-15T10:30:00Z", + "updatedAt": "2025-01-20T14:45:00Z" + } + ], + "pagination": { + "total": 1, + "take": 50, + "skip": 0, + "hasMore": false + } +} +\`\`\` + +--- + +### Get Brand + +Retrieve a specific brand by ID. + +\`\`\` +GET /api/v2/brand/brands/{brandId} +\`\`\` + +**Path Parameters:** +| Parameter | Type | Description | +|-----------|------|-------------| +| \`brandId\` | string | Brand ID (e.g., \`brand_123\`) | + +**Response:** +\`\`\`json +{ + "data": { + "id": "brand_123", + "name": "Acme Corp", + "manifestUrl": "https://storage.googleapis.com/...", + "createdAt": "2025-01-15T10:30:00Z", + "updatedAt": "2025-01-20T14:45:00Z" + } +} +\`\`\` + +--- + +### Create Brand + +Create a new brand with either a manifest URL or manifest JSON. + +\`\`\` +POST /api/v2/brand/brands +\`\`\` + +**Request Body (Option 1 - Manifest URL):** +\`\`\`json +{ + "manifestUrl": "https://example.com/brand-manifest.json" +} +\`\`\` + +**Request Body (Option 2 - Manifest JSON):** +\`\`\`json +{ + "manifestJson": { + "name": "Acme Corporation", + "url": "https://www.acme.com", + "logos": [ + { + "url": "https://acme.com/logo.png", + "tags": ["primary", "square"], + "width": 512, + "height": 512 + } + ], + "colors": { + "primary": "#FF5733", + "secondary": "#3366FF", + "text": "#333333", + "background": "#FFFFFF" + }, + "fonts": { + "primary": "Roboto", + "secondary": "Open Sans" + }, + "tone": "Professional, friendly, and innovative", + "tagline": "Innovation for Everyone", + "industry": "Technology", + "target_audience": "Small business owners aged 25-45" + } +} +\`\`\` + +**Response:** +\`\`\`json +{ + "data": { + "id": "brand_123", + "name": "Acme Corporation", + "manifestUrl": "https://storage.googleapis.com/...", + "createdAt": "2025-01-15T10:30:00Z", + "updatedAt": "2025-01-15T10:30:00Z" + } +} +\`\`\` + +--- + +### Update Brand + +Update an existing brand's manifest. + +\`\`\` +PUT /api/v2/brand/brands/{brandId} +\`\`\` + +**Path Parameters:** +| Parameter | Type | Description | +|-----------|------|-------------| +| \`brandId\` | string | Brand ID | + +**Request Body:** +Same as Create Brand - provide either \`manifestUrl\` or \`manifestJson\`. + +**Response:** +\`\`\`json +{ + "data": { + "id": "brand_123", + "name": "Acme Corporation", + "manifestUrl": "https://storage.googleapis.com/...", + "createdAt": "2025-01-15T10:30:00Z", + "updatedAt": "2025-01-20T14:45:00Z" + } +} +\`\`\` + +--- + +### Delete Brand + +Delete a brand. + +\`\`\` +DELETE /api/v2/brand/brands/{brandId} +\`\`\` + +**Path Parameters:** +| Parameter | Type | Description | +|-----------|------|-------------| +| \`brandId\` | string | Brand ID | + +**Response:** +HTTP 204 No Content (success, no body) + +--- + +## Complete Workflows + +### Workflow 1: Create a New Brand + +\`\`\` +Step 1: Create brand with manifest JSON +POST /api/v2/brand/brands +{ + "manifestJson": { + "name": "My Brand", + "url": "https://mybrand.com", + "colors": { + "primary": "#FF0000", + "secondary": "#0000FF" + }, + "tone": "Casual and fun", + "tagline": "Making life easier" + } +} +โ†’ Save the brand ID from response +\`\`\` + +### Workflow 2: Update Brand Identity + +\`\`\` +Step 1: List brands to find the one to update +GET /api/v2/brand/brands + +Step 2: Get current brand details +GET /api/v2/brand/brands/{brandId} +โ†’ Review current manifest + +Step 3: Update with new manifest +PUT /api/v2/brand/brands/{brandId} +{ + "manifestJson": { + "name": "My Brand - Updated", + "colors": { + "primary": "#00FF00" + }, + "tagline": "New and improved!" + } +} +\`\`\` + +--- + +## Brand Manifest Schema + +The full brand manifest JSON schema includes: + +| Field | Type | Description | +|-------|------|-------------| +| \`name\` | string | **Required.** Brand name | +| \`url\` | string | Brand website URL | +| \`logos\` | array | Array of logo objects with url, tags, width, height | +| \`colors\` | object | Color palette (primary, secondary, accent, background, text) | +| \`fonts\` | object | Typography (primary, secondary, font_urls) | +| \`tone\` | string | Brand voice and tone description | +| \`tagline\` | string | Brand slogan | +| \`assets\` | array | Brand assets (images, videos, audio) | +| \`product_catalog\` | object | Product feed configuration | +| \`disclaimers\` | array | Legal disclaimers | +| \`industry\` | string | Industry or sector | +| \`target_audience\` | string | Target audience description | +| \`contact\` | object | Contact information (email, phone, website) | +| \`metadata\` | object | Manifest metadata (version, dates) | + +--- + +## Error Handling + +All endpoints return standard error responses: + +\`\`\`json +{ + "error": { + "code": "VALIDATION_ERROR", + "message": "Invalid request body", + "details": { + "field": "manifestUrl", + "issue": "Invalid URL format" + } + } +} +\`\`\` + +### Common Error Codes + +| Code | Description | +|------|-------------| +| \`VALIDATION_ERROR\` | Invalid request parameters | +| \`UNAUTHORIZED\` | Authentication required | +| \`NOT_FOUND\` | Brand not found | +| \`INTERNAL_ERROR\` | Server error | + +--- + +## Common Mistakes to Avoid + +1. **Providing both manifestUrl and manifestJson** - Only provide one +2. **Missing required field** - Brand name is required in manifestJson +3. **Invalid color format** - Colors must be hex format (#RRGGBB) +4. **Invalid URL format** - URLs must be valid HTTP/HTTPS URLs +`; + +export const bundledPartnerSkillMd = `--- +name: scope3-agentic-partner +version: "2.0.0" +description: Scope3 Agentic Partner API - Publisher and seller integrations +api_base_url: https://api.agentic.scope3.com/api/v2/partner +auth: + type: bearer + header: Authorization + format: "Bearer {token}" + obtain_url: https://app.agentic.scope3.com/settings/api-keys +--- + +# Scope3 Agentic Partner API + +This API enables publishers and sellers to integrate with the Scope3 Agentic platform. + +**Important**: This is a REST API accessed via the \`api_call\` tool. After reading this documentation, use \`api_call\` to make HTTP requests to the endpoints below. + +## Current Status + +The Partner API v2 is currently in early development. Full partner endpoints (tactics, media buys, webhooks, segment management) will be added in future releases. + +## Quick Start + +1. **Use \`api_call\` tool**: All operations go through the generic \`api_call\` tool +2. **Base path**: All endpoints start with \`/api/v2/partner/\` +3. **Authentication**: Handled automatically by the MCP session + +--- + +## Available Endpoints + +### Health Check + +Verify the API is running and responsive. + +\`\`\`http +GET /api/v2/partner/health +\`\`\` + +**Response:** +\`\`\`json +{ + "status": "healthy", + "version": "2.0.0", + "apiVersion": "v2-partner", + "timestamp": "2025-01-20T14:45:00Z" +} +\`\`\` + +--- + +## Coming Soon + +The following features are planned for future releases: + +### Tactic Management +- Create and manage advertising tactics +- Configure targeting parameters +- Set pricing and availability + +### Media Buy Integration +- Receive media buy notifications +- Confirm or reject media buys +- Report delivery status + +### Segment Management +- Create audience segments +- Attach data to segments +- Manage segment availability + +### Webhooks +- Configure webhook endpoints +- Receive real-time notifications +- Track delivery events + +### Reporting +- Access performance metrics +- Revenue reporting +- Fill rate analytics + +--- + +## Error Handling + +All errors follow this format: +\`\`\`json +{ + "data": null, + "error": { + "code": "ERROR_CODE", + "message": "Human-readable message", + "details": {} + } +} +\`\`\` + +| Code | HTTP Status | Resolution | +|------|-------------|------------| +| \`VALIDATION_ERROR\` | 400 | Check request body against schema | +| \`UNAUTHORIZED\` | 401 | Verify API key/auth | +| \`ACCESS_DENIED\` | 403 | Check permissions | +| \`NOT_FOUND\` | 404 | Verify resource ID exists | +| \`RATE_LIMITED\` | 429 | Wait and retry | + +--- + +## Need Help? + +For questions about the Partner API or to request early access to new features, contact your Scope3 account representative. +`; + +export const bundledAt = '2026-02-10T00:00:00.000Z'; + +/** + * Get bundled skill.md for a persona + */ +export function getBundledSkillMd(persona: Persona = 'buyer'): string { + switch (persona) { + case 'buyer': + return bundledBuyerSkillMd; + case 'brand': + return bundledBrandSkillMd; + case 'partner': + return bundledPartnerSkillMd; + default: + return bundledBuyerSkillMd; + } +} diff --git a/src/skill/fetcher.ts b/src/skill/fetcher.ts new file mode 100644 index 0000000..b959685 --- /dev/null +++ b/src/skill/fetcher.ts @@ -0,0 +1,58 @@ +/** + * Fetcher for skill.md files + * Fetches from API with fallback to bundled version + */ + +import { getBundledSkillMd } from './bundled'; +import type { FetchSkillOptions } from './types'; +import { logger } from '../utils/logger'; + +const DEFAULT_BASE_URL = 'https://api.agentic.scope3.com'; +const DEFAULT_TIMEOUT = 5000; + +/** + * Fetch skill.md content from the API + * Falls back to bundled version on error + * + * @param options Fetch options + * @returns skill.md content as string + */ +export async function fetchSkillMd(options: FetchSkillOptions = {}): Promise { + const version = options.version ?? 'v2'; + const persona = options.persona ?? 'buyer'; + const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL; + const timeout = options.timeout ?? DEFAULT_TIMEOUT; + + // Build URL: /api/{version}/{persona}/skill.md + const versionPath = version === 'latest' ? 'v2' : version; + const url = `${baseUrl}/api/${versionPath}/${persona}/skill.md`; + + try { + const response = await fetch(url, { + signal: AbortSignal.timeout(timeout), + headers: { + Accept: 'text/markdown, text/plain, */*', + }, + }); + + if (response.ok) { + return response.text(); + } + + // Non-200 response, use fallback + logger.warn(`Failed to fetch skill.md (${response.status}), using bundled version`); + return getBundledSkillMd(persona); + } catch (error) { + // Network error or timeout, use fallback + if (error instanceof Error) { + logger.warn(`Failed to fetch skill.md: ${error.message}, using bundled version`); + } + return getBundledSkillMd(persona); + } +} + +/** + * Get the bundled skill.md content for a persona + * @deprecated Use getBundledSkillMd(persona) instead + */ +export { getBundledSkillMd }; diff --git a/src/skill/index.ts b/src/skill/index.ts new file mode 100644 index 0000000..7010dbd --- /dev/null +++ b/src/skill/index.ts @@ -0,0 +1,8 @@ +/** + * skill.md support + */ + +export * from './types'; +export { fetchSkillMd, getBundledSkillMd } from './fetcher'; +export { parseSkillMd } from './parser'; +export { bundledBuyerSkillMd, bundledBrandSkillMd, bundledPartnerSkillMd } from './bundled'; diff --git a/src/skill/parser.ts b/src/skill/parser.ts new file mode 100644 index 0000000..27be6f9 --- /dev/null +++ b/src/skill/parser.ts @@ -0,0 +1,216 @@ +/** + * Parser for skill.md files + * Extracts structured data from markdown format + */ + +import type { ParsedSkill, SkillCommand, SkillParameter, SkillExample } from './types'; + +/** + * Parse skill.md content into structured data + * + * @param content Raw skill.md content + * @returns Parsed skill structure + */ +export function parseSkillMd(content: string): ParsedSkill { + const skill: ParsedSkill = { + name: '', + version: '', + description: '', + apiBase: '', + commands: [], + examples: [], + }; + + // Parse YAML header (either --- front matter or ```yaml block) + const frontMatterMatch = content.match(/^---\n([\s\S]*?)\n---/); + const yamlBlockMatch = content.match(/```yaml\n([\s\S]*?)```/); + const yamlContent = frontMatterMatch?.[1] ?? yamlBlockMatch?.[1]; + if (yamlContent) { + skill.name = extractYamlValue(yamlContent, 'name') ?? ''; + skill.version = extractYamlValue(yamlContent, 'version') ?? ''; + skill.description = extractYamlValue(yamlContent, 'description') ?? ''; + skill.apiBase = + extractYamlValue(yamlContent, 'api_base_url') ?? + extractYamlValue(yamlContent, 'api_base') ?? + ''; + } + + // Parse command tables + skill.commands = parseCommandTables(content); + + // Parse code examples + skill.examples = parseExamples(content); + + return skill; +} + +/** + * Extract a value from simple YAML content + */ +function extractYamlValue(yaml: string, key: string): string | undefined { + const regex = new RegExp(`^${key}:\\s*(.+)$`, 'm'); + const match = yaml.match(regex); + return match ? match[1].trim().replace(/^["']|["']$/g, '') : undefined; +} + +/** + * Parse command tables from markdown + */ +function parseCommandTables(content: string): SkillCommand[] { + const commands: SkillCommand[] = []; + + // Match tables with Method | Endpoint | Description format + const tableRegex = /\| Method \| Endpoint \| Description \|\n\|[-|]+\|\n((?:\|[^\n]+\|\n?)+)/g; + + let match; + while ((match = tableRegex.exec(content)) !== null) { + const rows = match[1].trim().split('\n'); + + for (const row of rows) { + const cells = row + .split('|') + .filter(Boolean) + .map((c) => c.trim()); + + if (cells.length >= 3) { + const [method, endpoint, description] = cells; + + // Generate command name from endpoint + const name = generateCommandName(method, endpoint); + + commands.push({ + name, + method, + path: endpoint, + description, + parameters: extractParametersFromEndpoint(endpoint), + }); + } + } + } + + // Also parse MCP tools table + const mcpTableRegex = /\| Tool \| Operations \|\n\|[-|]+\|\n((?:\|[^\n]+\|\n?)+)/g; + + while ((match = mcpTableRegex.exec(content)) !== null) { + const rows = match[1].trim().split('\n'); + + for (const row of rows) { + const cells = row + .split('|') + .filter(Boolean) + .map((c) => c.trim()); + + if (cells.length >= 2) { + const [tool, operations] = cells; + const toolName = tool.replace(/`/g, ''); + const ops = operations.split(',').map((o) => o.trim()); + + for (const op of ops) { + commands.push({ + name: `${toolName} ${op}`, + mcpTool: toolName, + description: `${op} operation for ${toolName}`, + parameters: [], + }); + } + } + } + } + + return commands; +} + +/** + * Generate a command name from method and endpoint + */ +function generateCommandName(method: string, endpoint: string): string { + // Remove parameter placeholders and leading slash + const path = endpoint.replace(/\{[^}]+\}/g, '').replace(/^\//, ''); + const segments = path.split('/').filter(Boolean); + + // Build name from path + const resource = segments[0] || 'unknown'; + + // Determine action from method + let action: string; + switch (method.toUpperCase()) { + case 'GET': + action = endpoint.includes('{') ? 'get' : 'list'; + break; + case 'POST': + if (endpoint.includes('/execute')) action = 'execute'; + else if (endpoint.includes('/pause')) action = 'pause'; + else action = 'create'; + break; + case 'PUT': + case 'PATCH': + action = 'update'; + break; + case 'DELETE': + action = 'delete'; + break; + default: + action = method.toLowerCase(); + } + + // Handle nested resources + if (segments.length > 1 && segments[1] !== '{id}') { + return `${segments[0]} ${segments[1]} ${action}`; + } + + return `${resource} ${action}`; +} + +/** + * Extract parameters from endpoint path + */ +function extractParametersFromEndpoint(endpoint: string): SkillParameter[] { + const params: SkillParameter[] = []; + const paramRegex = /\{([^}]+)\}/g; + + let match; + while ((match = paramRegex.exec(endpoint)) !== null) { + params.push({ + name: match[1], + type: 'string', + required: true, + description: `${match[1]} parameter`, + }); + } + + return params; +} + +/** + * Parse code examples from markdown + */ +function parseExamples(content: string): SkillExample[] { + const examples: SkillExample[] = []; + + // Match code blocks with language + const codeBlockRegex = /```(\w+)\n([\s\S]*?)```/g; + + let match; + while ((match = codeBlockRegex.exec(content)) !== null) { + const [, language, code] = match; + + // Skip yaml header and workflow diagrams + if (language === 'yaml' || code.includes('โ†’')) { + continue; + } + + // Try to extract title from preceding text + const precedingText = content.slice(Math.max(0, match.index - 100), match.index); + const titleMatch = precedingText.match(/### ([^\n]+)\n?$/); + const title = titleMatch ? titleMatch[1] : `${language} example`; + + examples.push({ + title, + language, + code: code.trim(), + }); + } + + return examples; +} diff --git a/src/skill/types.ts b/src/skill/types.ts new file mode 100644 index 0000000..b730cd7 --- /dev/null +++ b/src/skill/types.ts @@ -0,0 +1,85 @@ +/** + * Types for skill.md parsing and representation + */ + +import type { ApiVersion, Persona } from '../types'; + +/** + * Parsed skill.md structure + */ +export interface ParsedSkill { + /** Skill name (e.g., 'scope3-agentic-buyer') */ + name: string; + /** Skill version (e.g., '2.0.0') */ + version: string; + /** Skill description */ + description: string; + /** API base URL */ + apiBase: string; + /** Persona this skill belongs to */ + persona?: Persona; + /** Available commands */ + commands: SkillCommand[]; + /** Usage examples */ + examples: SkillExample[]; +} + +/** + * A command available in the skill + */ +export interface SkillCommand { + /** Command name (e.g., 'advertisers list') */ + name: string; + /** HTTP method for REST */ + method?: string; + /** Endpoint path */ + path?: string; + /** MCP tool name */ + mcpTool?: string; + /** Command description */ + description: string; + /** Command parameters */ + parameters: SkillParameter[]; +} + +/** + * A parameter for a command + */ +export interface SkillParameter { + /** Parameter name */ + name: string; + /** Parameter type (string, number, boolean, object, array) */ + type: string; + /** Whether the parameter is required */ + required: boolean; + /** Parameter description */ + description: string; + /** Default value if any */ + defaultValue?: string; +} + +/** + * A usage example + */ +export interface SkillExample { + /** Example title/description */ + title: string; + /** Code language (bash, typescript, json) */ + language: string; + /** Example code */ + code: string; +} + +/** + * Options for fetching skill.md + */ +export interface FetchSkillOptions { + /** API version to fetch */ + version?: ApiVersion; + /** Persona to fetch skill.md for */ + persona?: Persona; + /** Base URL to fetch from */ + baseUrl?: string; + /** Fetch timeout in ms */ + timeout?: number; +} diff --git a/src/types/api.ts b/src/types/api.ts deleted file mode 100644 index dfcd654..0000000 --- a/src/types/api.ts +++ /dev/null @@ -1,5944 +0,0 @@ -/** - * This file was auto-generated by openapi-typescript. - * Do not make direct changes to the file. - */ - -export interface paths { - '/mcp-initialize': { - /** - * Initialize MCP session - * @description Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as a UUID and included in the mcp-session-id header for all subsequent requests. - */ - post: operations['mcp_initialize']; - }; - '/brand-agent-list': { - /** - * List brand agents - * @description List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. - */ - post: operations['brand_agent_list']; - }; - '/brand-agent-get': { - /** - * Get brand agent - * @description Get detailed information about a specific brand agent (advertiser account) by ID. - */ - post: operations['brand_agent_get']; - }; - '/brand-agent-create': { - /** - * Create brand agent - * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. - */ - post: operations['brand_agent_create']; - }; - '/brand-agent-update': { - /** - * Update brand agent - * @description Update an existing brand agent with new information. - */ - post: operations['brand_agent_update']; - }; - '/brand-agent-delete': { - /** - * Delete brand agent - * @description Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. - */ - post: operations['brand_agent_delete']; - }; - '/campaign-list': { - /** - * List campaigns - * @description List all campaigns with optional filtering by brand agent. - */ - post: operations['campaign_list']; - }; - '/campaign-create': { - /** - * Create campaign - * @description Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. - */ - post: operations['campaign_create']; - }; - '/campaign-get': { - /** - * Get campaign - * @description Get detailed information about a specific campaign. - */ - post: operations['campaign_get']; - }; - '/campaign-update': { - /** - * Update campaign - * @description Update an existing campaign with new information. - */ - post: operations['campaign_update']; - }; - '/campaign-delete': { - /** - * Delete campaign - * @description Delete a campaign and all associated resources. - */ - post: operations['campaign_delete']; - }; - '/campaign-get-summary': { - /** - * Get campaign summary - * @description Get a high-level summary of a campaign including key metrics and status. - */ - post: operations['campaign_get_summary']; - }; - '/campaign-list-tactics': { - /** - * List campaign tactics - * @description List all tactics associated with a specific campaign. - */ - post: operations['campaign_list_tactics']; - }; - '/campaign-validate-brief': { - /** - * Validate campaign brief - * @description Validate a campaign brief to ensure it contains all necessary information for campaign creation. - */ - post: operations['campaign_validate_brief']; - }; - '/asset-list': { - /** - * List assets - * @description List all uploaded assets with optional filtering by brand agent. - */ - post: operations['asset_list']; - }; - '/brand-standards-create': { - /** - * Create brand standards - * @description Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand agent. - */ - post: operations['brand_standards_create']; - }; - '/brand-standards-delete': { - /** - * Delete brand standards - * @description Delete brand standards for a brand agent. - */ - post: operations['brand_standards_delete']; - }; - '/brand-standards-list': { - /** - * List brand standards - * @description List all brand standards with optional filtering by brand agent. - */ - post: operations['brand_standards_list']; - }; - '/brand-story-create': { - /** - * Create brand story - * @description Create a brand story containing the narrative, history, values, and key messaging for a brand agent. - */ - post: operations['brand_story_create']; - }; - '/brand-story-update': { - /** - * Update brand story - * @description Update an existing brand story with new information. - */ - post: operations['brand_story_update']; - }; - '/brand-story-delete': { - /** - * Delete brand story - * @description Delete a brand story. - */ - post: operations['brand_story_delete']; - }; - '/brand-story-list': { - /** - * List brand stories - * @description List all brand stories with optional filtering by brand agent. - */ - post: operations['brand_story_list']; - }; - '/channel-list': { - /** - * List channels - * @description List all available advertising channels and platforms. - */ - post: operations['channel_list']; - }; - '/creative-assign': { - /** - * Assign creative - * @description Assign a creative to a tactic or media buy. - */ - post: operations['creative_assign']; - }; - '/creative-create': { - /** - * Create creative - * @description Create a new creative with assets, copy, and targeting specifications. - */ - post: operations['creative_create']; - }; - '/creative-update': { - /** - * Update creative - * @description Update an existing creative with new assets, copy, or specifications. - */ - post: operations['creative_update']; - }; - '/creative-delete': { - /** - * Delete creative - * @description Delete a creative and remove it from any associated tactics or media buys. - */ - post: operations['creative_delete']; - }; - '/creative-get': { - /** - * Get creative - * @description Get detailed information about a specific creative. - */ - post: operations['creative_get']; - }; - '/creative-list': { - /** - * List creatives - * @description List all creatives with optional filtering by brand agent or campaign. - */ - post: operations['creative_list']; - }; - '/creative-sync-sales-agents': { - /** - * Sync creatives to sales agents - * @description Synchronize creatives to connected sales agents (DSPs, publisher platforms). - */ - post: operations['creative_sync_sales_agents']; - }; - '/media-buy-create': { - /** - * Create media buy - * @description Create a new media buy with budget, targeting, and creative specifications. - */ - post: operations['media_buy_create']; - }; - '/media-buy-update': { - /** - * Update media buy - * @description Update an existing media buy with new budget, targeting, or creative assignments. - */ - post: operations['media_buy_update']; - }; - '/media-buy-delete': { - /** - * Delete media buy - * @description Delete a media buy and cancel any active placements. - */ - post: operations['media_buy_delete']; - }; - '/media-buy-execute': { - /** - * Execute media buy - * @description Execute a media buy, sending it to the configured sales agents for placement. - */ - post: operations['media_buy_execute']; - }; - '/media-buy-get': { - /** - * Get media buy - * @description Get detailed information about a specific media buy. - */ - post: operations['media_buy_get']; - }; - '/media-buy-list': { - /** - * List media buys - * @description List all media buys with optional filtering by brand agent, campaign, or status. - */ - post: operations['media_buy_list']; - }; - '/media-buy-validate-budget': { - /** - * Validate media buy budget - * @description Validate a media buy budget against campaign constraints and available funds. - */ - post: operations['media_buy_validate_budget']; - }; - '/notifications-list': { - /** - * List notifications - * @description List notifications for the authenticated user with optional filtering by status. - */ - post: operations['notifications_list']; - }; - '/notifications-mark-read': { - /** - * Mark notification as read - * @description Mark a specific notification as read. - */ - post: operations['notifications_mark_read']; - }; - '/notifications-mark-acknowledged': { - /** - * Mark notification as acknowledged - * @description Mark a specific notification as acknowledged. - */ - post: operations['notifications_mark_acknowledged']; - }; - '/notifications-mark-all-read': { - /** - * Mark all notifications as read - * @description Mark all notifications for the authenticated user as read. - */ - post: operations['notifications_mark_all_read']; - }; - '/media-product-discover': { - /** - * Discover media products - * @description Discover available media products from connected sales agents based on targeting criteria. - */ - post: operations['media_product_discover']; - }; - '/media-product-save': { - /** - * Save media product - * @description Save a discovered media product for future use in media buys. - */ - post: operations['media_product_save']; - }; - '/media-product-list': { - /** - * List media products - * @description List saved media products with optional filtering. - */ - post: operations['media_product_list']; - }; - '/media-product-sync': { - /** - * Sync media products - * @description Synchronize media product catalog from connected sales agents. - */ - post: operations['media_product_sync']; - }; - '/agent-get': { - /** - * Get agent - * @description Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the agent ID. - */ - post: operations['agent_get']; - }; - '/agent-list': { - /** - * List agents - * @description List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - */ - post: operations['agent_list']; - }; - '/agent-register': { - /** - * Register agent - * @description Register a new agent for media buying (SALES type) or outcome optimization (OUTCOME type). - */ - post: operations['agent_register']; - }; - '/agent-unregister': { - /** - * Unregister agent - * @description Unregister an agent and disconnect it from the platform. Type is automatically inferred from the agent ID. - */ - post: operations['agent_unregister']; - }; - '/agent-update': { - /** - * Update agent - * @description Update agent configuration and credentials. Type is automatically inferred from the agent ID. - */ - post: operations['agent_update']; - }; - '/sales-agent-get': { - /** - * Get sales agent (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_get instead. Get detailed information about a specific sales agent (DSP, publisher platform). - */ - post: operations['sales_agent_get']; - }; - '/sales-agent-list': { - /** - * List sales agents (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_list instead. List all registered sales agents (DSPs, publisher platforms). - */ - post: operations['sales_agent_list']; - }; - '/sales-agent-register': { - /** - * Register sales agent (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_register instead. Register a new sales agent (DSP, publisher platform) for media buying. - */ - post: operations['sales_agent_register']; - }; - '/sales-agent-unregister': { - /** - * Unregister sales agent (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_unregister instead. Unregister a sales agent and disconnect it from the platform. - */ - post: operations['sales_agent_unregister']; - }; - '/sales-agent-update': { - /** - * Update sales agent (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_update instead. Update sales agent configuration and credentials. - */ - post: operations['sales_agent_update']; - }; - '/sales-agent-account-list': { - /** - * List sales agent accounts - * @description List all accounts (seats, advertisers) within a sales agent. - */ - post: operations['sales_agent_account_list']; - }; - '/sales-agent-account-register': { - /** - * Register sales agent account - * @description Register a new account (seat, advertiser) within a sales agent. - */ - post: operations['sales_agent_account_register']; - }; - '/sales-agent-account-unregister': { - /** - * Unregister sales agent account - * @description Unregister an account from a sales agent. - */ - post: operations['sales_agent_account_unregister']; - }; - '/sales-agent-account-update': { - /** - * Update sales agent account - * @description Update account configuration within a sales agent. - */ - post: operations['sales_agent_account_update']; - }; - '/tactic-create': { - /** - * Create tactic - * @description Create a new tactic defining how to achieve campaign objectives. - */ - post: operations['tactic_create']; - }; - '/tactic-update': { - /** - * Update tactic - * @description Update an existing tactic with new targeting, budget, or creative requirements. - */ - post: operations['tactic_update']; - }; - '/tactic-delete': { - /** - * Delete tactic - * @description Delete a tactic and all associated media buys. - */ - post: operations['tactic_delete']; - }; - '/tactic-get': { - /** - * Get tactic - * @description Get detailed information about a specific tactic. - */ - post: operations['tactic_get']; - }; - '/tactic-list': { - /** - * List tactics - * @description List all tactics with optional filtering by brand agent or campaign. - */ - post: operations['tactic_list']; - }; - '/tactic-link-campaign': { - /** - * Link tactic to campaign - * @description Link a tactic to a campaign. - */ - post: operations['tactic_link_campaign']; - }; - '/tactic-unlink-campaign': { - /** - * Unlink tactic from campaign - * @description Unlink a tactic from a campaign. - */ - post: operations['tactic_unlink_campaign']; - }; - '/webhook-register': { - /** - * Register webhook - * @description Register a webhook to receive real-time notifications about events. - */ - post: operations['webhook_register']; - }; - '/webhook-list': { - /** - * List webhooks - * @description List all registered webhooks. - */ - post: operations['webhook_list']; - }; - '/webhook-delete': { - /** - * Delete webhook - * @description Delete a registered webhook. - */ - post: operations['webhook_delete']; - }; -} - -export type webhooks = Record; - -export interface components { - schemas: { - ListAssetsInput: { - /** @description Optional brand agent ID to filter assets */ - brandAgentId?: number; - }; - /** @description Parameters for listing brand agents. Authentication is automatic. */ - ListBrandAgentsInput: { - /** @description Prisma-style where clause for filtering agents */ - where?: { - [key: string]: unknown; - }; - /** @description Prisma-style orderBy clause */ - orderBy?: { - [key: string]: unknown; - }; - /** - * @description Number of records to return - * @example 10 - */ - take?: number; - /** - * @description Number of records to skip - * @example 0 - */ - skip?: number; - /** @description Fields to use for distinct selection */ - distinct?: string[]; - }; - /** @description Parameters for retrieving a specific brand agent */ - GetBrandAgentInput: { - /** - * @description The unique identifier for the brand agent - * @example 123 - */ - brandAgentId: number; - }; - /** @description Parameters for creating a new brand agent */ - CreateBrandAgentInput: { - /** - * @description Name of the brand agent (advertiser account) - * @example Nike Global Campaigns - */ - name: string; - /** - * @description Optional description of the brand agent - * @example Brand agent for Nike global advertising campaigns - */ - description?: string; - /** - * Format: uri - * @description URL to the brand manifest - * @example https://example.com/brand-manifest - */ - manifestUrl?: string; - /** - * @description Country codes (ISO 3166-1 alpha-2) - * @example [ - * "US", - * "CA", - * "GB" - * ] - */ - countryCodes?: string[]; - }; - /** @description Parameters for updating a brand agent */ - UpdateBrandAgentInput: { - /** - * @description The unique identifier for the brand agent - * @example 123 - */ - brandAgentId: number; - /** @description Updated name of the brand agent */ - name?: string; - /** @description Updated description */ - description?: string; - /** - * Format: uri - * @description Updated URL to the brand manifest - * @example https://example.com/brand-manifest - */ - manifestUrl?: string; - /** @description Updated country codes */ - countryCodes?: string[]; - }; - /** @description Parameters for deleting a brand agent */ - DeleteBrandAgentInput: { - /** - * @description The unique identifier for the brand agent to delete - * @example 123 - */ - brandAgentId: number; - }; - CreateBrandStandardInput: { - /** @description Brand agent ID */ - brandAgentId: number; - /** @description Standard name */ - name?: string; - /** @description Standard description */ - description?: string; - /** @description Brand standards prompt */ - prompt: string; - /** @description Whether this is the primary standard */ - isPrimary?: boolean; - /** @description Country codes */ - countries?: string[]; - /** @description Channel types */ - channels?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; - /** @description Brand names */ - brands?: string[]; - }; - DeleteBrandStandardInput: { - /** @description Brand standard ID */ - brandStandardId: string; - }; - ListBrandStandardsInput: { - /** @description Optional brand agent ID to filter brand standards by */ - brandAgentId?: number; - /** @description Prisma-style where clause for filtering standards */ - where?: { - [key: string]: unknown; - }; - /** @description Prisma-style orderBy clause */ - orderBy?: { - [key: string]: unknown; - }; - /** @description Number of records to return */ - take?: number; - /** @description Number of records to skip */ - skip?: number; - /** @description Fields to use for distinct selection */ - distinct?: string[]; - }; - CreateBrandStoryInput: { - /** @description Brand agent ID (bigint or string) */ - brandAgentId: number | string; - /** @description Story name */ - name: string; - /** @description Brand story prompt */ - prompt?: string; - /** @description Brand names */ - brands?: string[]; - /** @description Language codes (use language_list tool to see available options) */ - languages: string[]; - }; - UpdateBrandStoryInput: { - /** @description Brand story ID */ - brandStoryId: string; - /** @description Story name */ - name?: string; - /** @description Updated brand story prompt */ - prompt: string; - }; - DeleteBrandStoryInput: { - /** @description Brand story ID */ - brandStoryId: string; - }; - ListBrandStoriesInput: { - /** @description Optional brand agent ID to filter brand stories by */ - brandAgentId?: number; - /** @description Filtering criteria */ - where?: { - [key: string]: unknown; - }; - /** @description Ordering criteria */ - orderBy?: { - [key: string]: unknown; - }; - /** @description Number of records to return */ - take?: number; - /** @description Number of records to skip */ - skip?: number; - /** @description Fields to use for distinct selection */ - distinct?: string[]; - }; - /** @description Parameters for listing campaigns */ - ListCampaignsInput: { - /** - * @description Filter by brand agent ID - * @example 123 - */ - brandAgentId?: number; - /** - * @description Filter by campaign status - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; - /** - * @description Number of results to return - * @example 50 - */ - limit?: number; - /** - * @description Number of results to skip for pagination - * @example 0 - */ - offset?: number; - }; - /** @description Parameters for creating a new campaign */ - CreateCampaignInput: { - /** - * @description Brand agent ID that will own this campaign - * @example 123 - */ - brandAgentId: number; - /** - * @description Optional name for the campaign (auto-generated if not provided) - * @example Summer 2025 Tech Campaign - */ - name?: string; - /** - * @description Natural language description of campaign requirements. The backend will parse this to extract targeting, budget, and creative requirements. - * @example Create a video campaign targeting tech enthusiasts aged 25-45 with $50k budget - */ - prompt: string; - /** @description Budget configuration for the campaign */ - budget?: { - total: number; - /** @default USD */ - currency?: string; - dailyCap?: number; - /** @enum {string} */ - pacing?: 'EVEN' | 'ASAP' | 'FRONTLOADED'; - }; - /** - * Format: date-time - * @description Campaign start date (ISO 8601 format) - * @example 2025-01-15T00:00:00Z - */ - startDate?: string; - /** - * Format: date-time - * @description Campaign end date (ISO 8601 format) - * @example 2025-03-31T23:59:59Z - */ - endDate?: string; - /** @description Scoring weights for campaign optimization */ - scoringWeights?: { - affinity?: number; - outcome?: number; - quality?: number; - }; - /** - * @description Number of days for outcome measurement window - * @example 30 - */ - outcomeScoreWindowDays?: number; - /** - * @description Initial campaign status - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; - }; - /** @description Parameters for retrieving a specific campaign */ - GetCampaignInput: { - /** - * @description The unique identifier for the campaign - * @example cmp_987654321 - */ - campaignId: string; - }; - /** @description Parameters for updating a campaign */ - UpdateCampaignInput: { - /** - * @description The unique identifier for the campaign - * @example cmp_987654321 - */ - campaignId: string; - /** @description Updated campaign name */ - name?: string; - /** @description Updated campaign prompt */ - prompt?: string; - /** @description Updated budget configuration */ - budget?: { - total?: number; - /** @default USD */ - currency?: string; - dailyCap?: number; - /** @enum {string} */ - pacing?: 'EVEN' | 'ASAP' | 'FRONTLOADED'; - }; - /** - * Format: date-time - * @description Updated start date - */ - startDate?: string; - /** - * Format: date-time - * @description Updated end date - */ - endDate?: string; - /** @description Updated scoring weights */ - scoringWeights?: { - affinity?: number; - outcome?: number; - quality?: number; - }; - /** @description Updated outcome score window days */ - outcomeScoreWindowDays?: number; - /** - * @description Updated campaign status - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; - }; - /** @description Parameters for deleting a campaign */ - DeleteCampaignInput: { - /** - * @description The unique identifier for the campaign to delete - * @example cmp_987654321 - */ - campaignId: string; - /** @description If true, permanently delete the campaign. Default: false (soft delete/archive) */ - hardDelete?: boolean; - }; - GetCampaignSummaryInput: { - /** @description Campaign ID */ - campaignId: string; - }; - ListCampaignTacticsInput: { - /** @description Campaign ID */ - campaignId: string; - }; - ValidateBriefInput: { - /** @description Campaign brief text */ - brief: string; - }; - ListChannelsInput: Record; - AssignCreativeInput: { - creativeId: string; - campaignId: string; - }; - CreateCreativeInput: { - brandAgentId: number; - organizationId?: string; - name: string; - description?: string; - /** @enum {string} */ - formatSource?: 'ADCP' | 'CREATIVE_AGENT' | 'PUBLISHER'; - /** @description Format identifier. For ADCP sources, this should be a format ID string recognized by the target sales agent (e.g., display_300x250, video_1920x1080). Valid formats are agent-specific. */ - formatId?: string; - mediaUrl?: string; - /** @description Optional: Upload assets inline with the creative. Each asset requires: name, contentType, data (base64), and assetType. */ - assets?: { - /** @description Filename (e.g., banner.png) */ - name: string; - /** @description MIME type (e.g., image/png, image/jpeg) */ - contentType: string; - /** - * Format: byte - * @description Base64-encoded file data (without data:image/png;base64, prefix) - */ - data: string; - /** - * @description Type of asset - * @enum {string} - */ - assetType: 'image' | 'video' | 'audio' | 'logo' | 'font'; - /** @description Optional tags */ - tags?: string[]; - }[]; - content?: { - [key: string]: unknown; - }; - /** @enum {string} */ - assemblyMethod?: 'CREATIVE_AGENT' | 'ACTIVATION' | 'PUBLISHER'; - /** @description Optional campaign ID (object ID) to assign creative to */ - campaignId?: string; - }; - UpdateCreativeInput: { - creativeId: string; - name?: string; - status?: string; - }; - DeleteCreativeInput: { - creativeId: string; - }; - GetCreativeInput: { - creativeId: string; - }; - ListCreativesInput: { - campaignId?: number; - brandAgentId?: number; - /** @enum {string} */ - formatSource?: 'ADCP' | 'CREATIVE_AGENT' | 'PUBLISHER'; - /** @enum {string} */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; - take?: number; - skip?: number; - }; - SyncSalesAgentsInput: { - creativeId: string; - }; - CreateMediaBuyInput: { - tacticId: number; - agentId: string; - name: string; - description?: string; - products: { - mediaProductId: string; - budgetAmount: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creatives?: { - creative_id: string; - name: string; - format_id: - | string - | { - agent_url: string; - id: string; - }; - assets?: { - [key: string]: { - url: string; - width?: number; - height?: number; - }; - }; - click_url?: string; - }[]; - }[]; - creatives?: { - creative_id: string; - name: string; - format_id: - | string - | { - agent_url: string; - id: string; - }; - assets?: { - [key: string]: { - url: string; - width?: number; - height?: number; - }; - }; - click_url?: string; - }[]; - }; - UpdateMediaBuyInput: { - mediaBuyId: string; - name?: string; - description?: string; - /** @enum {string} */ - status?: - | 'DRAFT' - | 'PENDING_APPROVAL' - | 'ACTIVE' - | 'PAUSED' - | 'COMPLETED' - | 'FAILED' - | 'REJECTED'; - creativeIds?: string[]; - packages?: { - packageId: string; - creativeIds: string[]; - }[]; - }; - DeleteMediaBuyInput: { - mediaBuyId: string; - confirm: boolean; - }; - ExecuteMediaBuyInput: { - mediaBuyId: string; - }; - GetMediaBuyInput: { - mediaBuyId: string; - }; - ListMediaBuysInput: { - tacticId?: number; - /** @enum {string} */ - status?: - | 'DRAFT' - | 'PENDING_APPROVAL' - | 'ACTIVE' - | 'PAUSED' - | 'COMPLETED' - | 'FAILED' - | 'REJECTED'; - take?: number; - skip?: number; - }; - ValidateMediaBuyBudgetInput: { - tacticId: number; - newBudgetAmount: number; - }; - ListNotificationsInput: { - brandAgentId?: number; - campaignId?: string; - creativeId?: string; - tacticId?: string; - types?: string[]; - unreadOnly?: boolean; - limit?: number; - offset?: number; - }; - MarkNotificationReadInput: { - notificationId: string; - }; - MarkNotificationAcknowledgedInput: { - notificationId: string; - }; - MarkAllNotificationsReadInput: Record; - DiscoverProductsInput: { - campaignBrief?: string; - brandManifestUrl?: string; - /** @enum {string} */ - deliveryType?: 'guaranteed' | 'non_guaranteed'; - formats?: ('audio' | 'display' | 'html5' | 'native' | 'video')[]; - /** @enum {string} */ - inventoryType?: 'premium' | 'run_of_site' | 'targeted_package'; - maxCpm?: number; - minCpm?: number; - publisherIds?: string[]; - agentId?: string; - }; - SaveProductInput: { - productId: string; - name: string; - description: string; - publisherId: string; - publisherName: string; - /** @enum {string} */ - deliveryType: 'guaranteed' | 'non_guaranteed'; - /** @enum {string} */ - inventoryType: 'premium' | 'run_of_site' | 'targeted_package'; - creativeFormats?: - | string[] - | { - agent_url: string; - id: string; - }[]; - /** @enum {string} */ - pricingModel: 'auction' | 'fixed_cpm'; - fixedCpm?: number; - floorCpm?: number; - targetCpm?: number; - pricingOptions?: { - [key: string]: unknown; - }[]; - supportedTargeting?: string[]; - adcpAgentId?: string; - }; - ListProductsInput: { - take?: number; - skip?: number; - }; - SyncProductsInput: { - sourceId: string; - }; - GetAgentInput: { - /** @description The agent ID to retrieve */ - agentId: string; - }; - ListAgentsInput: { - /** - * @description Filter by agent type (SALES or OUTCOME) - * @enum {string} - */ - type?: 'SALES' | 'OUTCOME'; - /** - * @description Filter by status (PENDING, ACTIVE, DISABLED) - * @enum {string} - */ - status?: 'PENDING' | 'ACTIVE' | 'DISABLED'; - /** @description Filter by organization ID */ - organizationId?: string; - /** - * @description Filter by relationship (SELF = owned by you, SCOPE3 = Scope3-provided, MARKETPLACE = third-party marketplace agents) - * @enum {string} - */ - relationship?: 'SELF' | 'SCOPE3' | 'MARKETPLACE'; - /** @description Filter by agent name (partial match) */ - name?: string; - }; - RegisterAgentInput: { - /** - * @description The type of agent to register - * @enum {string} - */ - type: 'SALES' | 'OUTCOME'; - /** @description Agent name */ - name: string; - /** @description Agent description */ - description?: string; - /** - * Format: uri - * @description Agent endpoint URL - */ - endpointUrl: string; - /** - * @description Protocol used by the agent (MCP or A2A) - * @enum {string} - */ - protocol: 'MCP' | 'A2A'; - /** - * @description Authentication type - * @enum {string} - */ - authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH' | 'JWT'; - /** @description Organization ID */ - organizationId?: string; - /** @description Authentication configuration object */ - authConfig?: - | { - /** @enum {string} */ - type: 'jwt'; - privateKey: string; - issuer: string; - subject: string; - keyId: string; - scope: string; - /** Format: uri */ - tokenEndpointUrl: string; - /** Format: uri */ - audienceUrl: string; - /** @enum {string} */ - algorithm?: 'ES256' | 'RS256'; - environment?: string; - } - | { - auth: { - /** @enum {string} */ - type: 'bearer' | 'apikey' | 'api_key'; - token: string; - }; - } - | { - auth: { - /** @enum {string} */ - type: 'oauth' | 'oauth2'; - token: string; - }; - } - | Record; - }; - UnregisterAgentInput: { - /** @description The agent ID to unregister */ - agentId: string; - }; - UpdateAgentInput: { - /** @description The agent ID to update */ - agentId: string; - /** @description New agent name */ - name?: string; - /** @description New agent description */ - description?: string; - /** - * Format: uri - * @description New endpoint URL - */ - endpointUrl?: string; - /** - * @description New protocol - * @enum {string} - */ - protocol?: 'MCP' | 'A2A'; - /** - * @description New authentication type - * @enum {string} - */ - authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH' | 'JWT'; - /** @description New authentication configuration */ - authConfig?: - | { - /** @enum {string} */ - type: 'jwt'; - privateKey: string; - issuer: string; - subject: string; - keyId: string; - scope: string; - /** Format: uri */ - tokenEndpointUrl: string; - /** Format: uri */ - audienceUrl: string; - /** @enum {string} */ - algorithm?: 'ES256' | 'RS256'; - environment?: string; - } - | { - auth: { - /** @enum {string} */ - type: 'bearer' | 'apikey' | 'api_key'; - token: string; - }; - } - | { - auth: { - /** @enum {string} */ - type: 'oauth' | 'oauth2'; - token: string; - }; - } - | Record; - }; - GetSalesAgentInput: { - agentId: string; - }; - ListSalesAgentsInput: Record; - RegisterSalesAgentInput: { - name: string; - description?: string; - /** Format: uri */ - endpointUrl: string; - /** @enum {string} */ - protocol: 'MCP' | 'A2A'; - /** @enum {string} */ - authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH' | 'JWT'; - organizationId?: string; - authConfig?: - | { - /** @enum {string} */ - type: 'jwt'; - privateKey: string; - issuer: string; - subject: string; - keyId: string; - scope: string; - /** Format: uri */ - tokenEndpointUrl: string; - /** Format: uri */ - audienceUrl: string; - /** @enum {string} */ - algorithm?: 'ES256' | 'RS256'; - environment?: string; - } - | { - auth: { - /** @enum {string} */ - type: 'bearer' | 'apikey' | 'api_key'; - token: string; - }; - } - | { - auth: { - /** @enum {string} */ - type: 'oauth' | 'oauth2'; - token: string; - }; - } - | Record; - }; - UnregisterSalesAgentInput: { - agentId: string; - }; - UpdateSalesAgentInput: { - agentId: string; - name?: string; - description?: string; - /** Format: uri */ - endpointUrl?: string; - /** @enum {string} */ - protocol?: 'MCP' | 'A2A'; - /** @enum {string} */ - authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH' | 'JWT'; - authConfig?: - | { - /** @enum {string} */ - type: 'jwt'; - privateKey: string; - issuer: string; - subject: string; - keyId: string; - scope: string; - /** Format: uri */ - tokenEndpointUrl: string; - /** Format: uri */ - audienceUrl: string; - /** @enum {string} */ - algorithm?: 'ES256' | 'RS256'; - environment?: string; - } - | { - auth: { - /** @enum {string} */ - type: 'bearer' | 'apikey' | 'api_key'; - token: string; - }; - } - | { - auth: { - /** @enum {string} */ - type: 'oauth' | 'oauth2'; - token: string; - }; - } - | Record; - }; - ListSalesAgentAccountsInput: { - agentId: string; - }; - RegisterSalesAgentAccountInput: { - agentId: string; - accountIdentifier: string; - authConfig?: - | { - /** @enum {string} */ - type: 'jwt'; - privateKey: string; - issuer: string; - subject: string; - keyId: string; - scope: string; - /** Format: uri */ - tokenEndpointUrl: string; - /** Format: uri */ - audienceUrl: string; - /** @enum {string} */ - algorithm?: 'ES256' | 'RS256'; - environment?: string; - } - | { - auth: { - /** @enum {string} */ - type: 'bearer' | 'apikey' | 'api_key'; - token: string; - }; - } - | { - auth: { - /** @enum {string} */ - type: 'oauth' | 'oauth2'; - token: string; - }; - } - | Record; - }; - UnregisterSalesAgentAccountInput: { - accountId: string; - }; - UpdateSalesAgentAccountInput: { - accountId: string; - accountData: { - [key: string]: unknown; - }; - }; - CreateTacticInput: { - campaignId: string; - name: string; - prompt?: string; - channelCodes?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; - countryCodes?: string[]; - /** @description Language codes */ - languages?: string[]; - availableBrandStandards?: { - id: number; - name: string; - }[]; - availableBrandStory?: { - id: number; - name: string; - }[]; - }; - UpdateTacticInput: { - tacticId: number; - name?: string; - prompt?: string; - channelCodes?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; - countryCodes?: string[]; - availableBrandStandards?: { - id: number; - name: string; - }[]; - availableBrandStory?: { - id: number; - name: string; - }[]; - }; - DeleteTacticInput: { - tacticId: number; - confirm: boolean; - }; - GetTacticInput: { - tacticId: number; - }; - ListTacticsInput: { - campaignId?: string; - take?: number; - skip?: number; - }; - LinkCampaignToTacticInput: { - tacticId: number; - campaignId: string; - }; - UnlinkCampaignFromTacticInput: { - tacticId: number; - campaignId: string; - }; - RegisterWebhookInput: { - brandAgentId?: number; - endpoint: { - /** Format: uri */ - url: string; - /** @enum {string} */ - method: 'POST' | 'PUT'; - headers?: { - [key: string]: string; - }; - authentication?: { - /** @enum {string} */ - type: 'bearer' | 'basic' | 'hmac'; - credentials: string; - }; - }; - eventTypes: string[]; - filters?: { - campaigns?: string[]; - tactics?: string[]; - creatives?: string[]; - mediaBuys?: string[]; - metrics?: string[]; - /** @enum {string} */ - minSeverity?: 'info' | 'warning' | 'critical'; - }; - retryPolicy?: { - maxRetries?: number; - backoffMultiplier?: number; - maxBackoffSeconds?: number; - }; - }; - ListWebhooksInput: { - take?: number; - skip?: number; - }; - DeleteWebhookInput: { - webhookId: string; - }; - BrandAgentUpdate: { - id: number; - name: string; - description?: string; - /** Format: uri */ - manifestUrl?: string; - customerId: number; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - BrandStandardsCreate: { - id: string; - name: string; - description?: string; - countryCodes: string[]; - channelCodes: string[]; - brands: string[]; - models: { - id: string; - name: string; - prompt: string; - status: string | null; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - CampaignUpdate: { - campaignId: string; - name: string; - status: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - CreativeGet: { - creativeId: string; - name: string; - status: string; - campaignId?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - MediaBuyGet: { - id: string; - tacticId: number; - customerId: number; - name: string; - description?: string; - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** Format: date-time */ - archivedAt?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - TacticGet: { - id: number; - name: string; - prompt?: string; - campaignIds?: string[]; - channelCodes: string[]; - countryCodes: string[]; - mediaBuyCount?: number; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - /** Format: date-time */ - archivedAt?: string; - }; - MCPContent: { - /** @enum {string} */ - type: 'text'; - text: string; - }; - /** @description Bad request error response */ - BadRequest: { - error: string; - message?: string; - }; - /** @description Unauthorized error response */ - Unauthorized: { - error: string; - message?: string; - }; - /** @description Internal server error response */ - InternalError: { - error: string; - message?: string; - }; - AssetList: { - total: number; - items: { - assetId: string; - originalFilename: string; - assetType: string; - size: number; - brandAgentId: string; - customerId: number; - signedUrl: string; - tags?: string[]; - }[]; - }; - BrandAgentList: { - brandAgents: components['schemas']['BrandAgentUpdateOutput'][]; - total: number; - }; - BrandAgentDelete: { - success: boolean; - deletedId: number; - }; - BrandStandardsDelete: { - success: boolean; - id: string; - }; - BrandStandardsList: { - total: number; - items: components['schemas']['BrandStandardsCreateOutput'][]; - }; - BrandStoryCreate: { - id: string; - name: string; - brandAgentId?: string; - countryCodes?: string[]; - channelCodes?: string[]; - languages?: string[]; - brands?: string[]; - currentModel?: { - id: string; - name: string; - prompt: string; - status: string | null; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - BrandStoryUpdate: { - id: string; - name: string; - prompt?: string; - status?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - BrandStoryDelete: { - success: boolean; - id: string; - }; - BrandStoryList: { - total: number; - items: { - id: string; - name: string; - description?: string; - status: string; - type: string; - languages: string[]; - currentModel?: { - id: string; - name: string; - prompt: string; - status: string | null; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }[]; - }; - CampaignList: { - campaigns: components['schemas']['CampaignUpdateOutput'][]; - total: number; - }; - CampaignDelete: { - success: boolean; - deletedId: string; - }; - CampaignGetSummary: { - campaignId: string; - summary: { - [key: string]: unknown; - }; - }; - CampaignListTactics: { - tactics: unknown[]; - total: number; - }; - CampaignValidateBrief: { - valid: boolean; - feedback?: string; - }; - ChannelList: { - total: number; - items: { - channel: string; - displayName: string; - }[]; - }; - CreativeAssign: { - success: boolean; - creativeId: string; - campaignId: string; - }; - CreativeDelete: { - success: boolean; - id: string; - }; - CreativeList: { - items: components['schemas']['CreativeGetOutput'][]; - total: number; - }; - CreativeSyncSalesAgents: { - success: boolean; - creativeId: string; - campaignId?: string; - }; - MediaBuyDelete: { - success: boolean; - id: string; - }; - MediaBuyExecute: { - success: boolean; - mediaBuyId: string; - status: string; - adcpMediaBuyId?: string; - adcpStatus?: string; - }; - MediaBuyList: { - total: number; - items: components['schemas']['MediaBuyGetOutput'][]; - }; - MediaBuyValidateBudget: { - valid: boolean; - message?: string; - }; - NotificationsList: { - total: number; - hasMore: boolean; - items: { - id: string; - type: string; - data: { - [key: string]: unknown; - }; - read: boolean; - acknowledged: boolean; - /** Format: date-time */ - createdAt: string; - }[]; - }; - NotificationsMarkRead: { - success: boolean; - notificationId: string; - }; - NotificationsMarkAcknowledged: { - success: boolean; - notificationId: string; - }; - NotificationsMarkAllRead: { - success: boolean; - count: number; - }; - MediaProductDiscover: { - success: boolean; - productsFound: number; - productsSaved: number; - successfulAgents: number; - failedAgents: number; - products: { - productId: string; - name: string; - publisherName: string; - salesAgentId?: string; - salesAgentName?: string; - /** @enum {string} */ - deliveryType: 'guaranteed' | 'non_guaranteed'; - /** @enum {string} */ - inventoryType: 'premium' | 'run_of_site' | 'targeted_package'; - creativeFormats?: - | string[] - | { - agent_url: string; - id: string; - }[]; - fixedCpm?: number; - floorCpm?: number; - targetCpm?: number; - }[]; - }; - MediaProductSave: { - id: string; - productId: string; - name: string; - publisherId: string; - publisherName: string; - customerId: number; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - MediaProductList: { - total: number; - items: { - id: string; - productId: string; - name: string; - salesAgent?: string; - salesAgentId?: string; - salesAgentName?: string; - /** @enum {string} */ - deliveryType: 'guaranteed' | 'non_guaranteed'; - format?: string; - creativeFormats?: - | string[] - | { - agent_url: string; - id: string; - }[]; - }[]; - }; - MediaProductSync: { - success: boolean; - productsSaved: number; - }; - AgentGet: - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - authenticationType: string; - description?: string; - organizationId?: string; - registeredBy?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - } - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - authenticationType: string; - description?: string; - organizationId?: string; - registeredBy?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - customerAccountCount: number; - }; - AgentList: { - total: number; - items: ( - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - } - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - customerAccountCount: number; - } - )[]; - }; - AgentRegister: { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - endpointUrl: string; - }; - AgentUnregister: { - success: boolean; - agentId: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - }; - AgentUpdate: { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - }; - SalesAgentGet: { - agentId: string; - name: string; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - authenticationType: string; - description?: string; - customerAccountCount: number; - organizationId?: string; - registeredBy?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - SalesAgentList: { - total: number; - items: { - agentId: string; - name: string; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - customerAccountCount: number; - }[]; - }; - SalesAgentRegister: { - agentId: string; - name: string; - status: string; - endpointUrl: string; - }; - SalesAgentUnregister: { - success: boolean; - agentId: string; - }; - SalesAgentUpdate: { - agentId: string; - name: string; - status: string; - }; - SalesAgentAccountList: { - total: number; - items: { - id: string; - accountIdentifier: string; - status: string; - registeredBy?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }[]; - }; - SalesAgentAccountRegister: { - accountId: string; - adcpAgentId: string; - status: string; - }; - SalesAgentAccountUnregister: { - success: boolean; - agentId: string; - }; - SalesAgentAccountUpdate: { - id: string; - status: string; - }; - TacticCreate: { - id: number; - name: string; - prompt?: string; - campaignId: string; - channelCodes: string[]; - countryCodes: string[]; - /** Format: date-time */ - createdAt: string; - }; - TacticDelete: { - success: boolean; - tacticId: number; - }; - TacticList: { - total: number; - items: components['schemas']['TacticGetOutput'][]; - }; - TacticLinkCampaign: { - success: boolean; - tacticId: number; - campaignId: string; - }; - TacticUnlinkCampaign: { - success: boolean; - tacticId: number; - campaignId: string; - }; - WebhookRegister: { - id: string; - brandAgentId?: number; - endpoint: { - url: string; - method: string; - authenticationType?: string; - }; - eventTypes: string[]; - filters?: { - campaigns?: string[]; - tactics?: string[]; - creatives?: string[]; - mediaBuys?: string[]; - metrics?: string[]; - minSeverity?: string; - }; - retryPolicy: { - maxRetries: number; - backoffMultiplier: number; - maxBackoffSeconds: number; - }; - status: string; - testResult: { - success: boolean; - statusCode?: number; - error?: string; - }; - }; - WebhookList: { - total: number; - items: { - id: string; - status: string; - endpoint: { - url: string; - method: string; - authenticationType?: string; - }; - eventTypes: string[]; - brandAgentId?: number; - failureCount: number; - /** Format: date-time */ - lastSuccess?: string | null; - /** Format: date-time */ - lastFailure?: string | null; - /** Format: date-time */ - createdAt: string; - }[]; - }; - WebhookDelete: { - success: boolean; - webhookId: string; - }; - BrandAgentUpdateOutput: { - id: number; - name: string; - description?: string; - /** Format: uri */ - manifestUrl?: string; - customerId: number; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - BrandStandardsCreateOutput: { - id: string; - name: string; - description?: string; - countryCodes: string[]; - channelCodes: string[]; - brands: string[]; - models: { - id: string; - name: string; - prompt: string; - status: string | null; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - CampaignUpdateOutput: { - campaignId: string; - name: string; - status: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - CreativeGetOutput: { - creativeId: string; - name: string; - status: string; - campaignId?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - MediaBuyGetOutput: { - id: string; - tacticId: number; - customerId: number; - name: string; - description?: string; - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** Format: date-time */ - archivedAt?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - TacticGetOutput: { - id: number; - name: string; - prompt?: string; - campaignIds?: string[]; - channelCodes: string[]; - countryCodes: string[]; - mediaBuyCount?: number; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - /** Format: date-time */ - archivedAt?: string; - }; - BrandAgentGet: { - id: number; - name: string; - description?: string; - /** Format: uri */ - manifestUrl?: string; - customerId: number; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - BrandAgentCreate: { - id: number; - name: string; - description?: string; - /** Format: uri */ - manifestUrl?: string; - customerId: number; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - CampaignCreate: { - campaignId: string; - name: string; - status: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - CampaignGet: { - campaignId: string; - name: string; - status: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - CreativeCreate: { - creativeId: string; - name: string; - status: string; - campaignId?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - CreativeUpdate: { - creativeId: string; - name: string; - status: string; - campaignId?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - MediaBuyCreate: { - id: string; - tacticId: number; - customerId: number; - name: string; - description?: string; - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** Format: date-time */ - archivedAt?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - MediaBuyUpdate: { - id: string; - tacticId: number; - customerId: number; - name: string; - description?: string; - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** Format: date-time */ - archivedAt?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - TacticUpdate: { - id: number; - name: string; - prompt?: string; - campaignIds?: string[]; - channelCodes: string[]; - countryCodes: string[]; - mediaBuyCount?: number; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - /** Format: date-time */ - archivedAt?: string; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; -} - -export type $defs = Record; - -export type external = Record; - -export interface operations { - /** - * Initialize MCP session - * @description Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as a UUID and included in the mcp-session-id header for all subsequent requests. - */ - mcp_initialize: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Generate a new UUID for session initialization. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - jsonrpc: '2.0'; - id: string | number; - /** @enum {string} */ - method: 'initialize'; - params: { - /** @example 2024-11-05 */ - protocolVersion: string; - capabilities: Record; - clientInfo: { - name: string; - version: string; - }; - }; - }; - }; - }; - responses: { - /** @description Session initialized successfully */ - 200: { - content: { - 'application/json': { - /** @enum {string} */ - jsonrpc?: '2.0'; - id?: string | number; - result?: { - protocolVersion?: string; - capabilities?: Record; - serverInfo?: { - name?: string; - version?: string; - }; - }; - }; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - }; - }; - /** - * List brand agents - * @description List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. - */ - brand_agent_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_list'; - arguments: components['schemas']['ListBrandAgentsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get brand agent - * @description Get detailed information about a specific brand agent (advertiser account) by ID. - */ - brand_agent_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_get'; - arguments: components['schemas']['GetBrandAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create brand agent - * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. - */ - brand_agent_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_create'; - arguments: components['schemas']['CreateBrandAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update brand agent - * @description Update an existing brand agent with new information. - */ - brand_agent_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_update'; - arguments: components['schemas']['UpdateBrandAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete brand agent - * @description Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. - */ - brand_agent_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_delete'; - arguments: components['schemas']['DeleteBrandAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List campaigns - * @description List all campaigns with optional filtering by brand agent. - */ - campaign_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'campaign_list'; - arguments: components['schemas']['ListCampaignsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create campaign - * @description Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. - */ - campaign_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'campaign_create'; - arguments: components['schemas']['CreateCampaignInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get campaign - * @description Get detailed information about a specific campaign. - */ - campaign_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'campaign_get'; - arguments: components['schemas']['GetCampaignInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update campaign - * @description Update an existing campaign with new information. - */ - campaign_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'campaign_update'; - arguments: components['schemas']['UpdateCampaignInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete campaign - * @description Delete a campaign and all associated resources. - */ - campaign_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'campaign_delete'; - arguments: components['schemas']['DeleteCampaignInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get campaign summary - * @description Get a high-level summary of a campaign including key metrics and status. - */ - campaign_get_summary: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'campaign_get_summary'; - arguments: components['schemas']['GetCampaignSummaryInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignGetSummary']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List campaign tactics - * @description List all tactics associated with a specific campaign. - */ - campaign_list_tactics: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'campaign_list_tactics'; - arguments: components['schemas']['ListCampaignTacticsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignListTactics']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Validate campaign brief - * @description Validate a campaign brief to ensure it contains all necessary information for campaign creation. - */ - campaign_validate_brief: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'campaign_validate_brief'; - arguments: components['schemas']['ValidateBriefInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignValidateBrief']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List assets - * @description List all uploaded assets with optional filtering by brand agent. - */ - asset_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'asset_list'; - arguments: components['schemas']['ListAssetsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AssetList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create brand standards - * @description Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand agent. - */ - brand_standards_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_standards_create'; - arguments: components['schemas']['CreateBrandStandardInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStandardsCreateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete brand standards - * @description Delete brand standards for a brand agent. - */ - brand_standards_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_standards_delete'; - arguments: components['schemas']['DeleteBrandStandardInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStandardsDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List brand standards - * @description List all brand standards with optional filtering by brand agent. - */ - brand_standards_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_standards_list'; - arguments: components['schemas']['ListBrandStandardsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStandardsList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create brand story - * @description Create a brand story containing the narrative, history, values, and key messaging for a brand agent. - */ - brand_story_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_story_create'; - arguments: components['schemas']['CreateBrandStoryInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStoryCreate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update brand story - * @description Update an existing brand story with new information. - */ - brand_story_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_story_update'; - arguments: components['schemas']['UpdateBrandStoryInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStoryUpdate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete brand story - * @description Delete a brand story. - */ - brand_story_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_story_delete'; - arguments: components['schemas']['DeleteBrandStoryInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStoryDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List brand stories - * @description List all brand stories with optional filtering by brand agent. - */ - brand_story_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'brand_story_list'; - arguments: components['schemas']['ListBrandStoriesInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStoryList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List channels - * @description List all available advertising channels and platforms. - */ - channel_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'channel_list'; - arguments: components['schemas']['ListChannelsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['ChannelList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Assign creative - * @description Assign a creative to a tactic or media buy. - */ - creative_assign: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'creative_assign'; - arguments: components['schemas']['AssignCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeAssign']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create creative - * @description Create a new creative with assets, copy, and targeting specifications. - */ - creative_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'creative_create'; - arguments: components['schemas']['CreateCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update creative - * @description Update an existing creative with new assets, copy, or specifications. - */ - creative_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'creative_update'; - arguments: components['schemas']['UpdateCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete creative - * @description Delete a creative and remove it from any associated tactics or media buys. - */ - creative_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'creative_delete'; - arguments: components['schemas']['DeleteCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get creative - * @description Get detailed information about a specific creative. - */ - creative_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'creative_get'; - arguments: components['schemas']['GetCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List creatives - * @description List all creatives with optional filtering by brand agent or campaign. - */ - creative_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'creative_list'; - arguments: components['schemas']['ListCreativesInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Sync creatives to sales agents - * @description Synchronize creatives to connected sales agents (DSPs, publisher platforms). - */ - creative_sync_sales_agents: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'creative_sync_sales_agents'; - arguments: components['schemas']['SyncSalesAgentsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeSyncSalesAgents']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create media buy - * @description Create a new media buy with budget, targeting, and creative specifications. - */ - media_buy_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_create'; - arguments: components['schemas']['CreateMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update media buy - * @description Update an existing media buy with new budget, targeting, or creative assignments. - */ - media_buy_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_update'; - arguments: components['schemas']['UpdateMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete media buy - * @description Delete a media buy and cancel any active placements. - */ - media_buy_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_delete'; - arguments: components['schemas']['DeleteMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Execute media buy - * @description Execute a media buy, sending it to the configured sales agents for placement. - */ - media_buy_execute: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_execute'; - arguments: components['schemas']['ExecuteMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyExecute']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get media buy - * @description Get detailed information about a specific media buy. - */ - media_buy_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_get'; - arguments: components['schemas']['GetMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List media buys - * @description List all media buys with optional filtering by brand agent, campaign, or status. - */ - media_buy_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_list'; - arguments: components['schemas']['ListMediaBuysInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Validate media buy budget - * @description Validate a media buy budget against campaign constraints and available funds. - */ - media_buy_validate_budget: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_validate_budget'; - arguments: components['schemas']['ValidateMediaBuyBudgetInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyValidateBudget']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List notifications - * @description List notifications for the authenticated user with optional filtering by status. - */ - notifications_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'notifications_list'; - arguments: components['schemas']['ListNotificationsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['NotificationsList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Mark notification as read - * @description Mark a specific notification as read. - */ - notifications_mark_read: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'notifications_mark_read'; - arguments: components['schemas']['MarkNotificationReadInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['NotificationsMarkRead']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Mark notification as acknowledged - * @description Mark a specific notification as acknowledged. - */ - notifications_mark_acknowledged: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'notifications_mark_acknowledged'; - arguments: components['schemas']['MarkNotificationAcknowledgedInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['NotificationsMarkAcknowledged']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Mark all notifications as read - * @description Mark all notifications for the authenticated user as read. - */ - notifications_mark_all_read: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'notifications_mark_all_read'; - arguments: components['schemas']['MarkAllNotificationsReadInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['NotificationsMarkAllRead']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Discover media products - * @description Discover available media products from connected sales agents based on targeting criteria. - */ - media_product_discover: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_product_discover'; - arguments: components['schemas']['DiscoverProductsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaProductDiscover']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Save media product - * @description Save a discovered media product for future use in media buys. - */ - media_product_save: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_product_save'; - arguments: components['schemas']['SaveProductInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaProductSave']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List media products - * @description List saved media products with optional filtering. - */ - media_product_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_product_list'; - arguments: components['schemas']['ListProductsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaProductList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Sync media products - * @description Synchronize media product catalog from connected sales agents. - */ - media_product_sync: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'media_product_sync'; - arguments: components['schemas']['SyncProductsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaProductSync']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get agent - * @description Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the agent ID. - */ - agent_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'agent_get'; - arguments: components['schemas']['GetAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentGet']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List agents - * @description List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - */ - agent_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'agent_list'; - arguments: components['schemas']['ListAgentsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Register agent - * @description Register a new agent for media buying (SALES type) or outcome optimization (OUTCOME type). - */ - agent_register: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'agent_register'; - arguments: components['schemas']['RegisterAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentRegister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Unregister agent - * @description Unregister an agent and disconnect it from the platform. Type is automatically inferred from the agent ID. - */ - agent_unregister: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'agent_unregister'; - arguments: components['schemas']['UnregisterAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentUnregister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update agent - * @description Update agent configuration and credentials. Type is automatically inferred from the agent ID. - */ - agent_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'agent_update'; - arguments: components['schemas']['UpdateAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentUpdate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get sales agent (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_get instead. Get detailed information about a specific sales agent (DSP, publisher platform). - */ - sales_agent_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'sales_agent_get'; - arguments: components['schemas']['GetSalesAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['SalesAgentGet']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List sales agents (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_list instead. List all registered sales agents (DSPs, publisher platforms). - */ - sales_agent_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'sales_agent_list'; - arguments: components['schemas']['ListSalesAgentsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['SalesAgentList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Register sales agent (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_register instead. Register a new sales agent (DSP, publisher platform) for media buying. - */ - sales_agent_register: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'sales_agent_register'; - arguments: components['schemas']['RegisterSalesAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['SalesAgentRegister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Unregister sales agent (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_unregister instead. Unregister a sales agent and disconnect it from the platform. - */ - sales_agent_unregister: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'sales_agent_unregister'; - arguments: components['schemas']['UnregisterSalesAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['SalesAgentUnregister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update sales agent (DEPRECATED) - * @deprecated - * @description DEPRECATED: Use agent_update instead. Update sales agent configuration and credentials. - */ - sales_agent_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'sales_agent_update'; - arguments: components['schemas']['UpdateSalesAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['SalesAgentUpdate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List sales agent accounts - * @description List all accounts (seats, advertisers) within a sales agent. - */ - sales_agent_account_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'sales_agent_account_list'; - arguments: components['schemas']['ListSalesAgentAccountsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['SalesAgentAccountList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Register sales agent account - * @description Register a new account (seat, advertiser) within a sales agent. - */ - sales_agent_account_register: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'sales_agent_account_register'; - arguments: components['schemas']['RegisterSalesAgentAccountInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['SalesAgentAccountRegister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Unregister sales agent account - * @description Unregister an account from a sales agent. - */ - sales_agent_account_unregister: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'sales_agent_account_unregister'; - arguments: components['schemas']['UnregisterSalesAgentAccountInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['SalesAgentAccountUnregister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update sales agent account - * @description Update account configuration within a sales agent. - */ - sales_agent_account_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'sales_agent_account_update'; - arguments: components['schemas']['UpdateSalesAgentAccountInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['SalesAgentAccountUpdate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create tactic - * @description Create a new tactic defining how to achieve campaign objectives. - */ - tactic_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'tactic_create'; - arguments: components['schemas']['CreateTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticCreate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update tactic - * @description Update an existing tactic with new targeting, budget, or creative requirements. - */ - tactic_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'tactic_update'; - arguments: components['schemas']['UpdateTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete tactic - * @description Delete a tactic and all associated media buys. - */ - tactic_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'tactic_delete'; - arguments: components['schemas']['DeleteTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get tactic - * @description Get detailed information about a specific tactic. - */ - tactic_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'tactic_get'; - arguments: components['schemas']['GetTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List tactics - * @description List all tactics with optional filtering by brand agent or campaign. - */ - tactic_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'tactic_list'; - arguments: components['schemas']['ListTacticsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Link tactic to campaign - * @description Link a tactic to a campaign. - */ - tactic_link_campaign: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'tactic_link_campaign'; - arguments: components['schemas']['LinkCampaignToTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticLinkCampaign']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Unlink tactic from campaign - * @description Unlink a tactic from a campaign. - */ - tactic_unlink_campaign: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'tactic_unlink_campaign'; - arguments: components['schemas']['UnlinkCampaignFromTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticUnlinkCampaign']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Register webhook - * @description Register a webhook to receive real-time notifications about events. - */ - webhook_register: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'webhook_register'; - arguments: components['schemas']['RegisterWebhookInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['WebhookRegister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List webhooks - * @description List all registered webhooks. - */ - webhook_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'webhook_list'; - arguments: components['schemas']['ListWebhooksInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['WebhookList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete webhook - * @description Delete a registered webhook. - */ - webhook_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - tool: 'webhook_delete'; - arguments: components['schemas']['DeleteWebhookInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['WebhookDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; -} diff --git a/src/types/index.ts b/src/types/index.ts index b761740..0d057cf 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,28 +1,595 @@ -export interface ClientConfig { +/** + * Scope3 SDK Types + */ + +// ============================================================================ +// Core Configuration +// ============================================================================ + +/** API version supported by the SDK */ +export type ApiVersion = 'v1' | 'v2' | 'latest'; + +/** API persona - determines which API surface to use */ +export type Persona = 'buyer' | 'brand' | 'partner'; + +/** Environment for API endpoints */ +export type Environment = 'production' | 'staging'; + +/** Adapter type for communication protocol */ +export type AdapterType = 'rest' | 'mcp'; + +/** + * Configuration for Scope3Client + */ +export interface Scope3ClientConfig { + /** API key (Bearer token) for authentication */ apiKey: string; + /** API persona - buyer, brand, or partner */ + persona: Persona; + /** API version to use (default: 'v2') */ + version?: ApiVersion; + /** Environment (default: 'production') */ environment?: Environment; + /** Custom base URL (overrides environment) */ baseUrl?: string; + /** Adapter type: 'rest' for HTTP, 'mcp' for AI agents (default: 'rest') */ + adapter?: AdapterType; + /** Request timeout in ms (default: 30000) */ timeout?: number; + /** Enable debug logging */ debug?: boolean; } -export interface DebugInfo { - toolName: string; - request: Record; - response: unknown; - rawResponse?: string; - durationMs?: number; +// ============================================================================ +// API Response Wrappers +// ============================================================================ + +/** + * Standard API response envelope + */ +export interface ApiResponse { + data: T; + error?: ApiErrorResponse; +} + +/** + * Paginated API response envelope + */ +export interface PaginatedApiResponse { + data: T[]; + pagination: PaginationInfo; + error?: ApiErrorResponse; } -export interface ToolResponse { - success: boolean; - message?: string; - data?: T; +/** + * Pagination metadata from API + */ +export interface PaginationInfo { + total: number; + take: number; + skip: number; + hasMore: boolean; } -export interface ErrorResponse { - error: string; +/** + * Standard API error response + */ +export interface ApiErrorResponse { + code: string; + message: string; details?: Record; } -export type Environment = 'production' | 'staging'; +/** + * Pagination parameters for list requests + */ +export interface PaginationParams { + /** Maximum number of results (default: 50, max: 250) */ + take?: number; + /** Number of results to skip */ + skip?: number; +} + +// ============================================================================ +// Advertiser Types (Buyer Persona) +// ============================================================================ + +export type AdvertiserStatus = 'ACTIVE' | 'ARCHIVED'; + +export interface Advertiser { + id: string; + name: string; + description?: string; + status: AdvertiserStatus; + createdAt: string; + updatedAt: string; +} + +export interface CreateAdvertiserInput { + name: string; + description?: string; +} + +export interface UpdateAdvertiserInput { + name?: string; + description?: string; +} + +export interface ListAdvertisersParams extends PaginationParams { + status?: AdvertiserStatus; + name?: string; +} + +// ============================================================================ +// Brand Types (Brand Persona - standalone) +// ============================================================================ + +export interface Brand { + id: string; + name: string; + manifestUrl?: string; + createdAt: string; + updatedAt: string; +} + +export interface CreateBrandInput { + manifestUrl?: string; + manifestJson?: BrandManifest; +} + +export interface UpdateBrandInput { + manifestUrl?: string; + manifestJson?: BrandManifest; +} + +export interface ListBrandsParams extends PaginationParams { + status?: string; + name?: string; +} + +/** + * Brand manifest document (ADCP v2) + */ +export interface BrandManifest { + name: string; + url?: string; + logos?: BrandLogo[]; + colors?: BrandColors; + fonts?: BrandFonts; + tone?: string; + tagline?: string; + assets?: BrandAsset[]; + product_catalog?: Record; + disclaimers?: string[]; + industry?: string; + target_audience?: string; + contact?: Record; + metadata?: Record; +} + +export interface BrandLogo { + url: string; + tags?: string[]; + width?: number; + height?: number; +} + +export interface BrandColors { + primary?: string; + secondary?: string; + accent?: string; + background?: string; + text?: string; +} + +export interface BrandFonts { + primary?: string; + secondary?: string; + font_urls?: string[]; +} + +export interface BrandAsset { + url: string; + type: string; + name?: string; +} + +// ============================================================================ +// Buyer Linked Brand Types (brand linked to advertiser) +// ============================================================================ + +export interface LinkedBrand { + brandId: string; + advertiserId: string; + brand?: Brand; +} + +export interface LinkBrandInput { + brandId: string; +} + +// ============================================================================ +// Campaign Types (Buyer Persona) +// ============================================================================ + +export type CampaignStatus = 'DRAFT' | 'ACTIVE' | 'PAUSED' | 'COMPLETED' | 'ARCHIVED'; +export type CampaignType = 'bundle' | 'performance' | 'audience'; +export type BudgetPacing = 'EVEN' | 'ASAP' | 'FRONTLOADED'; +export type PerformanceObjective = 'ROAS' | 'CONVERSIONS' | 'LEADS' | 'SALES'; + +export interface FlightDates { + startDate: string; + endDate: string; +} + +export interface Budget { + total: number; + currency?: string; + dailyCap?: number; + pacing?: BudgetPacing; +} + +export interface CampaignConstraints { + channels?: string[]; + countries?: string[]; +} + +export interface PerformanceConfig { + objective: PerformanceObjective; + goals?: { + targetRoas?: number; + }; +} + +export interface Campaign { + id: string; + advertiserId: string; + name: string; + type: CampaignType; + status: CampaignStatus; + flightDates: FlightDates; + budget: Budget; + brief?: string; + constraints?: CampaignConstraints; + bundleId?: string; + performanceConfig?: PerformanceConfig; + createdAt: string; + updatedAt: string; +} + +/** Input for creating a bundle campaign */ +export interface CreateBundleCampaignInput { + advertiserId: string; + name: string; + bundleId: string; + flightDates: FlightDates; + budget: Budget; + productIds?: string[]; + constraints?: CampaignConstraints; + brief?: string; +} + +/** Input for updating a bundle campaign */ +export interface UpdateBundleCampaignInput { + name?: string; + flightDates?: FlightDates; + budget?: Budget; + productIds?: string[]; + constraints?: CampaignConstraints; + brief?: string; +} + +/** Input for creating a performance campaign */ +export interface CreatePerformanceCampaignInput { + advertiserId: string; + name: string; + flightDates: FlightDates; + budget: Budget; + performanceConfig: PerformanceConfig; + constraints?: CampaignConstraints; +} + +/** Input for updating a performance campaign */ +export interface UpdatePerformanceCampaignInput { + name?: string; + flightDates?: FlightDates; + budget?: Budget; + performanceConfig?: PerformanceConfig; + constraints?: CampaignConstraints; +} + +/** Input for creating an audience campaign (not yet implemented) */ +export interface CreateAudienceCampaignInput { + advertiserId: string; + name: string; + flightDates: FlightDates; + budget: Budget; + signals?: string[]; + constraints?: CampaignConstraints; +} + +export interface ListCampaignsParams extends PaginationParams { + advertiserId?: string; + type?: CampaignType; + status?: CampaignStatus; +} + +// ============================================================================ +// Bundle Types (Buyer Persona) +// ============================================================================ + +export interface Bundle { + bundleId: string; +} + +export interface CreateBundleInput { + advertiserId: string; + channels?: string[]; + countries?: string[]; + brief?: string; + budget?: number; + flightDates?: FlightDates; +} + +/** Parameters for discovering products in a bundle */ +export interface DiscoverProductsParams { + /** Max groups to return (default: 10, max: 50) */ + groupLimit?: number; + /** Groups to skip for pagination */ + groupOffset?: number; + /** Products per group (default: 5, max: 50) */ + productsPerGroup?: number; + /** Filter by publisher domain */ + publisherDomain?: string; +} + +/** Response from discover-products endpoint */ +export interface DiscoverProductsResponse { + bundleId: string; + productGroups: ProductGroup[]; + totalGroups: number; + hasMoreGroups: boolean; + summary: ProductSummary; + budgetContext?: BudgetContext; +} + +export interface ProductGroup { + groupId: string; + groupName: string; + products: Product[]; + productCount: number; +} + +export interface Product { + productId: string; + name: string; + publisher: string; + channel: string; + cpm: number; + salesAgentId: string; +} + +export interface ProductSummary { + totalProducts: number; + publishersCount: number; + priceRange?: { + min: number; + max: number; + avg: number; + }; +} + +export interface BudgetContext { + sessionBudget: number; + allocatedBudget: number; + remainingBudget: number; +} + +/** Product selection for adding to a bundle */ +export interface BundleProductInput { + productId: string; + salesAgentId: string; + groupId: string; + groupName: string; + cpm?: number; + budget?: number; +} + +export interface AddBundleProductsInput { + products: BundleProductInput[]; +} + +export interface RemoveBundleProductsInput { + productIds: string[]; +} + +export interface BundleProductsResponse { + bundleId: string; + products: SelectedBundleProduct[]; + totalProducts: number; + budgetContext?: BudgetContext; +} + +export interface SelectedBundleProduct { + productId: string; + salesAgentId: string; + cpm?: number; + budget?: number; + selectedAt: string; + groupId: string; + groupName: string; +} + +/** Input for browse products without a campaign */ +export interface BrowseProductsInput { + advertiserId: string; + channels?: string[]; + countries?: string[]; + brief?: string; + publisherDomain?: string; +} + +// ============================================================================ +// Conversion Event Types (Buyer Persona) +// ============================================================================ + +export type ConversionEventType = + | 'PURCHASE' + | 'SIGNUP' + | 'LEAD' + | 'PAGE_VIEW' + | 'ADD_TO_CART' + | 'CUSTOM'; + +export interface ConversionEvent { + id: string; + name: string; + type: ConversionEventType; + description?: string; + value?: number; + currency?: string; + createdAt: string; + updatedAt: string; +} + +export interface CreateConversionEventInput { + name: string; + type: ConversionEventType; + description?: string; + value?: number; + currency?: string; +} + +export interface UpdateConversionEventInput { + name?: string; + value?: number; + currency?: string; + description?: string; +} + +// ============================================================================ +// Creative Set Types (Buyer Persona) +// ============================================================================ + +export interface CreativeSet { + id: string; + name: string; + type: string; + createdAt: string; + updatedAt: string; +} + +export interface CreateCreativeSetInput { + name: string; + type: string; +} + +export interface CreativeAsset { + id: string; + assetUrl: string; + name: string; + type: string; + duration?: number; +} + +export interface CreateCreativeAssetInput { + assetUrl: string; + name: string; + type: string; + duration?: number; +} + +// ============================================================================ +// Test Cohort Types (Buyer Persona) +// ============================================================================ + +export interface TestCohort { + id: string; + name: string; + description?: string; + splitPercentage: number; + createdAt: string; + updatedAt: string; +} + +export interface CreateTestCohortInput { + name: string; + description?: string; + splitPercentage: number; +} + +// ============================================================================ +// Reporting Types (Buyer Persona) +// ============================================================================ + +export interface ReportingParams { + days?: number; + startDate?: string; + endDate?: string; + campaignId?: string; + mediaBuyId?: string; +} + +export interface ReportingResponse { + dailyMetrics: DailyMetric[]; + totals: MetricTotals; + periodStart: string; + periodEnd: string; +} + +export interface DailyMetric { + date: string; + impressions: number; + clicks: number; + spend: number; +} + +export interface MetricTotals { + impressions: number; + clicks: number; + spend: number; +} + +// ============================================================================ +// Media Buy Types (Buyer Persona) +// ============================================================================ + +export interface MediaBuy { + id: string; + campaignId: string; + status: string; + createdAt: string; + updatedAt: string; +} + +export interface ListMediaBuysParams extends PaginationParams { + campaignId?: string; +} + +// ============================================================================ +// Signal Types (Buyer Persona) +// ============================================================================ + +export interface Signal { + id: string; + name: string; + type: string; + catalogType?: string; +} + +export interface DiscoverSignalsInput { + filters?: { + catalogTypes?: string[]; + }; +} + +// ============================================================================ +// Partner Types +// ============================================================================ + +export interface HealthCheckResponse { + status: string; + version: string; + apiVersion: string; + timestamp: string; +} diff --git a/src/types/media-agent-api.ts b/src/types/media-agent-api.ts deleted file mode 100644 index 384a426..0000000 --- a/src/types/media-agent-api.ts +++ /dev/null @@ -1,771 +0,0 @@ -/** - * This file was auto-generated by openapi-typescript. - * Do not make direct changes to the file. - */ - -export interface paths { - '/get-proposed-tactics': { - /** - * Get tactic proposals from your agent - * @description Scope3 calls this endpoint when setting up a campaign to ask what tactics - * your agent can handle and how you would approach execution. - * - * Analyze the campaign and respond with proposed tactics, budget capacity, - * and your pricing model. - */ - post: operations['get_proposed_tactics']; - }; - '/manage-tactic': { - /** - * Accept or decline tactic assignment - * @description Scope3 calls this when your agent is assigned to manage a tactic. - * You should acknowledge and begin setup, or decline if you can't fulfill it. - * - * The tactic context contains everything you need: budget, schedule, - * targeting constraints, creatives, and any custom fields. - */ - post: operations['manage_tactic']; - }; - '/tactic-context-updated': { - /** - * Notification of tactic changes - * @description Scope3 calls this when a tactic is modified by the user or their agent. - * Changes may include budget adjustments, schedule changes, or other updates. - * - * Your agent MUST handle these changes as they may impact targeting, - * delivery, or budget allocation. - */ - post: operations['tactic_context_updated']; - }; - '/tactic-creatives-updated': { - /** - * Notification of creative changes - * @description Scope3 calls this when creatives are added, removed, or modified for a tactic. - * - * Update your media buys to use the new creative assets. - */ - post: operations['tactic_creatives_updated']; - }; - '/tactic-feedback': { - /** - * Performance feedback from orchestrator - * @description Scope3 sends performance feedback to help you optimize delivery. - * - * - deliveryIndex: 100 = on target, <100 = under-delivering, >100 = over-delivering - * - performanceIndex: 100 = maximum, relative to target or other tactics - * - * Your agent MAY use this to adjust targeting, budget allocation, or other settings. - */ - post: operations['tactic_feedback']; - }; -} - -export type webhooks = Record; - -export interface components { - schemas: { - /** @description Budget range for campaign planning (buyer typically won't reveal full budget) */ - BudgetRange: { - /** - * @description Minimum budget available - * @example 50000 - */ - min?: number; - /** - * @description Maximum budget available - * @example 150000 - */ - max?: number; - /** - * @description Currency for budget (ISO 4217 code) - * @default USD - * @example USD - */ - currency?: string; - }; - TacticPricing: { - /** - * @description How the media agent charges for this tactic (passthrough, revshare, or cost_per_unit) - * @example revshare - * @enum {string} - */ - method: 'passthrough' | 'revshare' | 'cost_per_unit'; - /** - * @description Rate for the pricing method (e.g., 0.15 for 15% revshare, 2.50 for $2.50 CPM) - * @example 0.15 - */ - rate: number; - /** - * @description Currency for pricing (ISO 4217 code) - * @default USD - * @example USD - */ - currency?: string; - }; - CustomField: { - /** - * @description Name of the custom field - * @example targetVCPM - */ - fieldName?: string; - /** - * @description Data type of the field - * @example number - * @enum {string} - */ - fieldType?: 'string' | 'number' | 'boolean' | 'array' | 'object'; - /** - * @description Help text explaining what this field does - * @example Target vCPM in USD - */ - description?: string; - }; - GetProposedTacticsRequest: { - /** - * @description Campaign ID - * @example camp_123 - */ - campaignId: string; - budgetRange?: components['schemas']['BudgetRange']; - /** - * Format: date-time - * @description Campaign start date in UTC (ISO 8601 format) - * @example 2025-01-01T00:00:00Z - */ - startDate?: string; - /** - * Format: date-time - * @description Campaign end date in UTC (ISO 8601 format) - * @example 2025-01-31T23:59:59Z - */ - endDate?: string; - /** - * @description Advertising channels (aligned with AdCP channel schema) - * @example [ - * "display", - * "video" - * ] - */ - channels?: ('display' | 'video' | 'audio' | 'native' | 'ctv')[]; - /** - * @description ISO 3166-1 alpha-2 country codes - * @example [ - * "US", - * "CA" - * ] - */ - countries?: string[]; - /** - * @description Campaign objectives/outcomes (e.g., awareness, consideration, conversion) - * @example [ - * "awareness", - * "consideration" - * ] - */ - objectives?: string[]; - /** - * @description Campaign brief text - * @example Launch campaign for new product... - */ - brief?: string; - /** - * @description AdCP pricing models acceptable to the buyer for sales agent pricing - * @example [ - * "cpm", - * "vcpm", - * "flat_rate" - * ] - */ - acceptedPricingMethods?: ('cpm' | 'vcpm' | 'cpc' | 'cpcv' | 'cpv' | 'cpp' | 'flat_rate')[]; - promotedOfferings?: components['schemas']['PromotedOfferings']; - /** - * @description Seat/account ID for this request - * @example seat_456 - */ - seatId: string; - }; - ProposedTactic: { - /** - * @description Unique identifier for this proposed tactic (you generate this) - * @example premium-vcpm-display - */ - tacticId: string; - /** - * @description How you would execute this tactic - * @example Target premium inventory at $2.50 vCPM with 85% viewability - */ - execution: string; - /** - * @description Maximum budget you can effectively manage - * @example 50000 - */ - budgetCapacity: number; - pricing: components['schemas']['TacticPricing']; - /** - * @description Identifier for this tactic type - * @example premium-vcpm - */ - sku?: string; - /** @description Custom fields needed to execute this tactic */ - customFieldsRequired?: components['schemas']['CustomField'][]; - }; - GetProposedTacticsResponse: { - /** @description List of tactics you can handle (empty array if none) */ - proposedTactics?: components['schemas']['ProposedTactic'][]; - }; - TacticContext: { - /** - * @description Budget allocated - * @example 50000 - */ - budget?: number; - /** - * @description Currency for budget (ISO 4217 code) - * @default USD - * @example USD - */ - budgetCurrency?: string; - /** - * Format: date-time - * @description Tactic start date in UTC (ISO 8601 format) - * @example 2025-01-01T00:00:00Z - */ - startDate?: string; - /** - * Format: date-time - * @description Tactic end date in UTC (ISO 8601 format) - * @example 2025-01-31T23:59:59Z - */ - endDate?: string; - /** - * @description Advertising channel (aligned with AdCP channel schema) - * @example display - * @enum {string} - */ - channel?: 'display' | 'video' | 'audio' | 'native' | 'ctv'; - /** - * @description Target countries - * @example [ - * "US" - * ] - */ - countries?: string[]; - /** @description Creative assets to use (uses Creative from main schema) */ - creatives?: components['schemas']['Creative'][]; - /** @description Brand safety and suitability requirements (uses BrandStandard from main schema) */ - brandStandards?: components['schemas']['BrandStandard'][]; - }; - ManageTacticRequest: { - /** - * @description ID of the tactic (matches one you proposed) - * @example premium-vcpm-display - */ - tacticId: string; - tacticContext: components['schemas']['TacticContext']; - /** - * @description Brand agent (advertiser) for this campaign - * @example ba_123 - */ - brandAgentId: string; - /** - * @description Seat/account ID - * @example seat_456 - */ - seatId: string; - /** - * @description Custom fields provided by advertiser - * @example { - * "targetVCPM": 2.5 - * } - */ - customFields?: Record; - }; - ManageTacticResponse: { - /** - * @description true to accept assignment, false to decline - * @example true - */ - acknowledged: boolean; - /** - * @description Optional reason if declining - * @example Insufficient budget for effective optimization - */ - reason?: string; - }; - PatchOperation: { - /** - * @description Patch operation type - * @example replace - * @enum {string} - */ - op?: 'add' | 'remove' | 'replace'; - /** - * @description JSON Pointer to changed field - * @example /budget - */ - path?: string; - /** @description New value for the field */ - value?: unknown; - }; - TacticContextUpdatedRequest: { - /** - * @description Tactic ID - * @example premium-vcpm-display - */ - tacticId: string; - /** @description Current tactic state (after changes) */ - tactic: Record; - /** @description Changes in JSON Patch format (RFC 6902) */ - patch: components['schemas']['PatchOperation'][]; - }; - TacticCreativesUpdatedRequest: { - /** - * @description Tactic ID - * @example premium-vcpm-display - */ - tacticId: string; - /** @description Updated creative assets */ - creatives: components['schemas']['Creative'][]; - /** @description Changes to creatives array in JSON Patch format */ - patch: components['schemas']['PatchOperation'][]; - }; - Creative: { - /** - * @description Unique identifier for the creative - * @example cr_001 - */ - creativeId: string; - /** - * @description Name of the creative - * @example Summer Campaign Banner - */ - name: string; - /** - * @description Status of the creative - * @example ACTIVE - */ - status: string; - /** - * @description Campaign this creative belongs to (optional) - * @example camp_123 - */ - campaignId?: string; - /** - * Format: date-time - * @description When the creative was created (ISO 8601 UTC) - * @example 2025-01-01T00:00:00Z - */ - createdAt: string; - /** - * Format: date-time - * @description When the creative was last updated (ISO 8601 UTC) - * @example 2025-01-15T14:30:00Z - */ - updatedAt: string; - }; - BrandStandard: { - /** - * @description Unique identifier for the brand standard - * @example bs_001 - */ - id: string; - /** - * @description Name of the brand standard - * @example Premium Brand Safety - */ - name: string; - /** - * @description Description of the standard (optional) - * @example High viewability requirements for premium inventory - */ - description?: string; - /** - * @description ISO 3166-1 alpha-2 country codes this standard applies to - * @example [ - * "US", - * "CA" - * ] - */ - countryCodes: string[]; - /** - * @description Channels this standard applies to - * @example [ - * "display", - * "video" - * ] - */ - channelCodes: string[]; - /** - * @description Brand names this standard applies to - * @example [ - * "Brand A", - * "Brand B" - * ] - */ - brands: string[]; - /** - * Format: date-time - * @description When the standard was created (ISO 8601 UTC) - * @example 2025-01-01T00:00:00Z - */ - createdAt: string; - /** - * Format: date-time - * @description When the standard was last updated (ISO 8601 UTC) - * @example 2025-01-15T14:30:00Z - */ - updatedAt: string; - }; - TacticFeedbackRequest: { - /** - * @description Tactic ID - * @example premium-vcpm-display - */ - tacticId: string; - /** - * Format: date-time - * @description Start of feedback interval in UTC (ISO 8601 format) - * @example 2025-01-01T00:00:00Z - */ - startDate: string; - /** - * Format: date-time - * @description End of feedback interval in UTC (ISO 8601 format) - * @example 2025-01-07T23:59:59Z - */ - endDate: string; - /** - * @description Delivery performance (100 = on target) - * @example 95 - */ - deliveryIndex: number; - /** - * @description Performance vs target or peers (100 = maximum) - * @example 110 - */ - performanceIndex: number; - }; - /** @description Complete offering specification combining brand manifest, product selectors, and inline offerings (AdCP spec) */ - PromotedOfferings: { - /** @description Brand information manifest (inline object or URL reference) */ - brand_manifest: components['schemas']['BrandManifest'] | string; - /** @description Optional product catalog selectors */ - product_selectors?: { - /** - * @description Specific product IDs to promote - * @example [ - * "prod_123", - * "prod_456" - * ] - */ - product_ids?: string[]; - }; - /** @description Inline offerings for campaigns without a product catalog */ - offerings?: { - /** - * @description Offering name - * @example Winter Sale - */ - name: string; - /** - * @description Description of what's being offered - * @example 20% off all winter products - */ - description?: string; - /** @description Assets specific to this offering */ - assets?: Record[]; - }[]; - }; - /** @description Brand information manifest containing assets, themes, and guidelines (AdCP spec) */ - BrandManifest: { - /** - * Format: uri - * @description Primary brand URL for context and asset discovery - * @example https://brand.example.com - */ - url?: string; - /** - * @description Brand or business name - * @example Acme Corporation - */ - name?: string; - /** @description Brand logo assets with semantic tags */ - logos?: { - /** - * Format: uri - * @description URL to the logo asset - * @example https://cdn.example.com/logo.png - */ - url: string; - /** - * @description Semantic tags (e.g., 'dark', 'light', 'square', 'horizontal', 'icon') - * @example [ - * "dark", - * "horizontal" - * ] - */ - tags?: string[]; - /** - * @description Logo width in pixels - * @example 200 - */ - width?: number; - /** - * @description Logo height in pixels - * @example 50 - */ - height?: number; - }[]; - /** @description Brand color palette */ - colors?: { - /** - * @description Primary brand color (hex) - * @example #0D9373 - */ - primary?: string; - /** - * @description Secondary brand color (hex) - * @example #07C983 - */ - secondary?: string; - /** @description Accent color (hex) */ - accent?: string; - /** @description Background color (hex) */ - background?: string; - /** @description Text color (hex) */ - text?: string; - }; - /** @description Brand typography guidelines */ - fonts?: { - /** - * @description Primary font family name - * @example Inter - */ - primary?: string; - /** - * @description Secondary font family name - * @example Georgia - */ - secondary?: string; - /** @description URLs to web font files if using custom fonts */ - font_urls?: string[]; - }; - /** - * @description Brand voice and messaging tone - * @example professional - */ - tone?: string; - /** - * @description Brand tagline or slogan - * @example Innovation that moves you forward - */ - tagline?: string; - /** @description Product catalog information for e-commerce advertisers (enables SKU-level creative generation) */ - product_catalog?: { - /** - * Format: uri - * @description URL to product catalog feed - * @example https://brand.example.com/products.xml - */ - feed_url: string; - /** - * @description Format of the product feed - * @enum {string} - */ - feed_format?: 'google_merchant_center' | 'facebook_catalog' | 'custom'; - /** - * @description Product categories available in the catalog - * @example [ - * "electronics", - * "apparel", - * "home_goods" - * ] - */ - categories?: string[]; - /** - * Format: date-time - * @description When the product catalog was last updated - */ - last_updated?: string; - /** - * @description How frequently the product catalog is updated - * @enum {string} - */ - update_frequency?: 'realtime' | 'hourly' | 'daily' | 'weekly'; - }; - /** - * @description Industry or vertical - * @example retail - */ - industry?: string; - /** - * @description Primary target audience description - * @example Tech-savvy millennials aged 25-40 - */ - target_audience?: string; - /** @description Legal disclaimers or required text that must appear in creatives */ - disclaimers?: { - /** @description Disclaimer text */ - text: string; - /** @description When this disclaimer applies (e.g., financial_products, all) */ - context?: string; - /** @description Whether this disclaimer must appear */ - required?: boolean; - }[]; - /** @description Brand contact information */ - contact?: { - /** - * Format: email - * @description Contact email - */ - email?: string; - /** @description Contact phone number */ - phone?: string; - }; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; -} - -export type $defs = Record; - -export type external = Record; - -export interface operations { - /** - * Get tactic proposals from your agent - * @description Scope3 calls this endpoint when setting up a campaign to ask what tactics - * your agent can handle and how you would approach execution. - * - * Analyze the campaign and respond with proposed tactics, budget capacity, - * and your pricing model. - */ - get_proposed_tactics: { - requestBody: { - content: { - 'application/json': components['schemas']['GetProposedTacticsRequest']; - }; - }; - responses: { - /** @description Tactic proposals from your agent */ - 200: { - content: { - 'application/json': components['schemas']['GetProposedTacticsResponse']; - }; - }; - /** @description Invalid request */ - 400: { - content: never; - }; - /** @description Internal error */ - 500: { - content: never; - }; - }; - }; - /** - * Accept or decline tactic assignment - * @description Scope3 calls this when your agent is assigned to manage a tactic. - * You should acknowledge and begin setup, or decline if you can't fulfill it. - * - * The tactic context contains everything you need: budget, schedule, - * targeting constraints, creatives, and any custom fields. - */ - manage_tactic: { - requestBody: { - content: { - 'application/json': components['schemas']['ManageTacticRequest']; - }; - }; - responses: { - /** @description Acknowledgment of tactic assignment */ - 200: { - content: { - 'application/json': components['schemas']['ManageTacticResponse']; - }; - }; - /** @description Invalid request */ - 400: { - content: never; - }; - }; - }; - /** - * Notification of tactic changes - * @description Scope3 calls this when a tactic is modified by the user or their agent. - * Changes may include budget adjustments, schedule changes, or other updates. - * - * Your agent MUST handle these changes as they may impact targeting, - * delivery, or budget allocation. - */ - tactic_context_updated: { - requestBody: { - content: { - 'application/json': components['schemas']['TacticContextUpdatedRequest']; - }; - }; - responses: { - /** @description Acknowledged */ - 200: { - content: never; - }; - /** @description Invalid request */ - 400: { - content: never; - }; - }; - }; - /** - * Notification of creative changes - * @description Scope3 calls this when creatives are added, removed, or modified for a tactic. - * - * Update your media buys to use the new creative assets. - */ - tactic_creatives_updated: { - requestBody: { - content: { - 'application/json': components['schemas']['TacticCreativesUpdatedRequest']; - }; - }; - responses: { - /** @description Acknowledged */ - 200: { - content: never; - }; - /** @description Invalid request */ - 400: { - content: never; - }; - }; - }; - /** - * Performance feedback from orchestrator - * @description Scope3 sends performance feedback to help you optimize delivery. - * - * - deliveryIndex: 100 = on target, <100 = under-delivering, >100 = over-delivering - * - performanceIndex: 100 = maximum, relative to target or other tactics - * - * Your agent MAY use this to adjust targeting, budget allocation, or other settings. - */ - tactic_feedback: { - requestBody: { - content: { - 'application/json': components['schemas']['TacticFeedbackRequest']; - }; - }; - responses: { - /** @description Acknowledged */ - 200: { - content: never; - }; - /** @description Invalid request */ - 400: { - content: never; - }; - }; - }; -} diff --git a/src/types/outcome-agent-api.ts b/src/types/outcome-agent-api.ts deleted file mode 100644 index e5aef35..0000000 --- a/src/types/outcome-agent-api.ts +++ /dev/null @@ -1,377 +0,0 @@ -/** - * This file was auto-generated by openapi-typescript. - * Do not make direct changes to the file. - */ - -export interface paths { - '/get-proposals': { - /** - * Get proposals from your agent - * @description Scope3 calls this endpoint when setting up a campaign to ask for proposals - * from your agent on how you would approach execution. - * - * Analyze the campaign and respond with proposals, budget capacity, - * and your pricing model. - */ - post: operations['get_proposed_tactics']; - }; - '/accept-proposal': { - /** - * Accept or decline proposal assignment - * @description Scope3 calls this when your proposal is accepted and you are assigned to manage a tactic. - * You should acknowledge and begin setup, or decline if you can't fulfill it. - * - * The campaign context contains everything you need: budget, schedule, - * targeting constraints, creatives, and any custom fields. - */ - post: operations['accept_proposal']; - }; -} - -export type webhooks = Record; - -export interface components { - schemas: { - /** @description Budget range for campaign planning (buyer typically won't reveal full budget) */ - BudgetRange: { - /** - * @description Minimum budget available - * @example 50000 - */ - min?: number; - /** - * @description Maximum budget available - * @example 150000 - */ - max?: number; - /** - * @description Currency for budget (ISO 4217 code) - * @default USD - * @example USD - */ - currency?: string; - }; - TacticPricing: { - /** - * @description How the outcome agent charges for this tactic (revshare or cost_per_unit) - * @example revshare - * @enum {string} - */ - method: 'revshare' | 'cost_per_unit'; - /** - * @description Rate for the pricing method (e.g., 0.15 for 15% revshare, 2.50 for $2.50 CPM) - * @example 0.15 - */ - rate: number; - /** - * @description Pricing unit (required when method is cost_per_unit) - * @example cpm - * @enum {string} - */ - unit?: 'cpm' | 'cpc' | 'cpa' | 'cpv' | 'cpcv'; - /** - * @description Currency for pricing (ISO 4217 code) - * @default USD - * @example USD - */ - currency?: string; - }; - CustomField: { - /** - * @description Name of the custom field - * @example targetVCPM - */ - fieldName?: string; - /** - * @description Data type of the field - * @example number - * @enum {string} - */ - fieldType?: 'string' | 'number' | 'boolean' | 'array' | 'object'; - /** - * @description Help text explaining what this field does - * @example Target vCPM in USD - */ - description?: string; - }; - /** @description Product reference from sales agent */ - Product: { - /** - * @description URL of the sales agent offering this product - * @example https://sales-agent.example.com - */ - sales_agent_url: string; - /** - * @description Product reference ID from the sales agent - * @example prod_premium_display - */ - product_ref: string; - /** - * @description Pricing option ID for this product - * @example pricing_opt_123 - */ - pricing_option_id: string; - }; - GetProposalsRequest: { - /** - * @description Campaign ID - * @example camp_123 - */ - campaignId: string; - budgetRange?: components['schemas']['BudgetRange']; - /** - * Format: date-time - * @description Campaign start date in UTC (ISO 8601 format) - * @example 2025-01-01T00:00:00Z - */ - startDate?: string; - /** - * Format: date-time - * @description Campaign end date in UTC (ISO 8601 format) - * @example 2025-01-31T23:59:59Z - */ - endDate?: string; - /** - * @description Advertising channels (from ADCP specification) - * @example [ - * "display", - * "video" - * ] - */ - channels?: ('display' | 'video' | 'native' | 'audio' | 'connected_tv')[]; - /** - * @description ISO 3166-1 alpha-2 country codes - * @example [ - * "US", - * "CA" - * ] - */ - countries?: string[]; - /** - * @description Campaign brief text - * @example Launch campaign for new product... - */ - brief?: string; - /** @description Optional product objects to include in proposals (full product details, not just IDs) */ - products?: components['schemas']['Product'][]; - /** - * @description Optional property list IDs for targeting (references Scope3 property lists) - * @example [ - * 123, - * 456 - * ] - */ - propertyListIds?: number[]; - /** - * @description Seat/account ID for this request - * @example seat_456 - */ - seatId: string; - }; - Proposal: { - /** - * @description Unique identifier for this proposal (you generate this). The tactic ID will be assigned when the proposal is accepted. - * @example premium-vcpm-display - */ - proposalId: string; - /** - * @description How you would execute this proposal - * @example Target premium inventory at $2.50 vCPM with 85% viewability - */ - execution: string; - /** - * @description Maximum budget you can effectively manage - * @example 50000 - */ - budgetCapacity: number; - pricing: components['schemas']['TacticPricing']; - /** - * @description Identifier for this tactic type - * @example premium-vcpm - */ - sku?: string; - /** @description Custom fields needed to execute this proposal */ - customFieldsRequired?: components['schemas']['CustomField'][]; - /** - * @description Generic blob to store additional information about the proposal that will be passed back when accepted - * @example { - * "property_list": [ - * "prop1", - * "prop2" - * ], - * "custom_data": "value" - * } - */ - additional_info?: Record; - }; - GetProposalsResponse: { - /** @description List of proposals you can provide (empty array if none) */ - proposals?: components['schemas']['Proposal'][]; - }; - CampaignContext: { - /** - * @description Budget allocated - * @example 50000 - */ - budget?: number; - /** - * @description Currency for budget (ISO 4217 code) - * @default USD - * @example USD - */ - budgetCurrency?: string; - /** - * Format: date-time - * @description Campaign start date in UTC (ISO 8601 format) - * @example 2025-01-01T00:00:00Z - */ - startDate?: string; - /** - * Format: date-time - * @description Campaign end date in UTC (ISO 8601 format) - * @example 2025-01-31T23:59:59Z - */ - endDate?: string; - /** - * @description Advertising channel (from ADCP specification) - * @example display - * @enum {string} - */ - channel?: 'display' | 'video' | 'native' | 'audio' | 'connected_tv'; - /** - * @description Target countries - * @example [ - * "US" - * ] - */ - countries?: string[]; - /** @description Creative assets to use (uses Creative from main schema) */ - creatives?: components['schemas']['Creative'][]; - /** @description Brand safety and suitability requirements (uses BrandStandard from main schema) */ - brandStandards?: components['schemas']['BrandStandard'][]; - }; - AcceptProposalRequest: { - /** - * @description ID of the tactic from the strategy table (assigned when user accepts your proposal) - * @example 12345 - */ - tacticId: string; - /** - * @description ID of the proposal that was accepted (matches proposalId from GetProposalsResponse) - * @example premium-vcpm-display - */ - proposalId?: string; - campaignContext: components['schemas']['CampaignContext']; - /** - * @description Brand agent (advertiser) for this campaign - * @example ba_123 - */ - brandAgentId: string; - /** - * @description Seat/account ID - * @example seat_456 - */ - seatId: string; - /** - * @description Custom fields provided by advertiser - * @example { - * "targetVCPM": 2.5 - * } - */ - customFields?: Record; - /** - * @description The additional_info blob that was returned in the proposal response - * @example { - * "property_list": [ - * "prop1", - * "prop2" - * ], - * "custom_data": "value" - * } - */ - additional_info?: Record; - }; - AcceptProposalResponse: { - /** - * @description true to accept assignment, false to decline - * @example true - */ - acknowledged: boolean; - /** - * @description Optional reason if declining - * @example Insufficient budget for effective optimization - */ - reason?: string; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; -} - -export type $defs = Record; - -export type external = Record; - -export interface operations { - /** - * Get proposals from your agent - * @description Scope3 calls this endpoint when setting up a campaign to ask for proposals - * from your agent on how you would approach execution. - * - * Analyze the campaign and respond with proposals, budget capacity, - * and your pricing model. - */ - get_proposed_tactics: { - requestBody: { - content: { - 'application/json': components['schemas']['GetProposalsRequest']; - }; - }; - responses: { - /** @description Proposals from your agent */ - 200: { - content: { - 'application/json': components['schemas']['GetProposalsResponse']; - }; - }; - /** @description Invalid request */ - 400: { - content: never; - }; - /** @description Internal error */ - 500: { - content: never; - }; - }; - }; - /** - * Accept or decline proposal assignment - * @description Scope3 calls this when your proposal is accepted and you are assigned to manage a tactic. - * You should acknowledge and begin setup, or decline if you can't fulfill it. - * - * The campaign context contains everything you need: budget, schedule, - * targeting constraints, creatives, and any custom fields. - */ - accept_proposal: { - requestBody: { - content: { - 'application/json': components['schemas']['AcceptProposalRequest']; - }; - }; - responses: { - /** @description Acknowledgment of tactic assignment */ - 200: { - content: { - 'application/json': components['schemas']['AcceptProposalResponse']; - }; - }; - /** @description Invalid request */ - 400: { - content: never; - }; - }; - }; -} diff --git a/src/types/partner-api.ts b/src/types/partner-api.ts deleted file mode 100644 index 85ffea6..0000000 --- a/src/types/partner-api.ts +++ /dev/null @@ -1,4660 +0,0 @@ -/** - * This file was auto-generated by openapi-typescript. - * Do not make direct changes to the file. - */ - -export interface paths { - '/mcp-initialize': { - /** - * Initialize MCP session - * @description Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as a UUID and included in the mcp-session-id header for all subsequent requests. - */ - post: operations['mcp_initialize']; - }; - '/channel-list': { - /** - * List channels - * @description List all available advertising channels and platforms. - */ - post: operations['channel_list']; - }; - '/country-list': { - /** - * List countries - * @description Get all available countries for targeting. Use this to get valid country codes before creating brand agents. - */ - post: operations['country_list']; - }; - '/language-list': { - /** - * List languages - * @description Get all available languages for targeting. Use this to get valid language codes before creating brand stories. - */ - post: operations['language_list']; - }; - '/creative-sync-sales-agents': { - /** - * Sync creatives to sales agents - * @description Synchronize creatives to connected sales agents (DSPs, publisher platforms). - */ - post: operations['creative_sync_sales_agents']; - }; - '/media-buy-create': { - /** - * Create media buy - * @description Create a new media buy with budget, targeting, and creative specifications. - */ - post: operations['media_buy_create']; - }; - '/media-buy-update': { - /** - * Update media buy - * @description Update an existing media buy with new budget, targeting, or creative assignments. - */ - post: operations['media_buy_update']; - }; - '/media-buy-delete': { - /** - * Delete media buy - * @description Delete a media buy and cancel any active placements. - */ - post: operations['media_buy_delete']; - }; - '/media-buy-execute': { - /** - * Execute media buy - * @description Execute a media buy, sending it to the configured sales agents for placement. - */ - post: operations['media_buy_execute']; - }; - '/media-buy-get': { - /** - * Get media buy - * @description Get detailed information about a specific media buy. - */ - post: operations['media_buy_get']; - }; - '/media-buy-list': { - /** - * List media buys - * @description List all media buys with optional filtering by brand agent, campaign, or status. - */ - post: operations['media_buy_list']; - }; - '/media-buy-validate-budget': { - /** - * Validate media buy budget - * @description Validate a media buy budget against campaign constraints and available funds. - */ - post: operations['media_buy_validate_budget']; - }; - '/notifications-list': { - /** - * List notifications - * @description List notifications for the authenticated user with optional filtering by status. - */ - post: operations['notifications_list']; - }; - '/notifications-mark-read': { - /** - * Mark notification as read - * @description Mark a specific notification as read. - */ - post: operations['notifications_mark_read']; - }; - '/notifications-mark-acknowledged': { - /** - * Mark notification as acknowledged - * @description Mark a specific notification as acknowledged. - */ - post: operations['notifications_mark_acknowledged']; - }; - '/notifications-mark-all-read': { - /** - * Mark all notifications as read - * @description Mark all notifications for the authenticated user as read. - */ - post: operations['notifications_mark_all_read']; - }; - '/media-product-discover': { - /** - * Discover media products - * @description Discover available media products from connected sales agents based on targeting criteria. - */ - post: operations['media_product_discover']; - }; - '/media-product-save': { - /** - * Save media product - * @description Save a discovered media product for future use in media buys. - */ - post: operations['media_product_save']; - }; - '/media-product-list': { - /** - * List media products - * @description List saved media products with optional filtering. - */ - post: operations['media_product_list']; - }; - '/media-product-sync': { - /** - * Sync media products - * @description Synchronize media product catalog from connected sales agents. - */ - post: operations['media_product_sync']; - }; - '/agent-get': { - /** - * Get agent - * @description Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the agent ID. - */ - post: operations['agent_get']; - }; - '/agent-list': { - /** - * List agents - * @description List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - */ - post: operations['agent_list']; - }; - '/agent-register': { - /** - * Register agent - * @description Register a new agent for media buying (SALES type) or outcome optimization (OUTCOME type). - */ - post: operations['agent_register']; - }; - '/agent-unregister': { - /** - * Unregister agent - * @description Unregister an agent and disconnect it from the platform. Type is automatically inferred from the agent ID. - */ - post: operations['agent_unregister']; - }; - '/agent-update': { - /** - * Update agent - * @description Update agent configuration and credentials. Type is automatically inferred from the agent ID. - */ - post: operations['agent_update']; - }; - '/tactic-create': { - /** - * Create tactic - * @description Create a new tactic defining how to achieve campaign objectives. - */ - post: operations['tactic_create']; - }; - '/tactic-update': { - /** - * Update tactic - * @description Update an existing tactic with new targeting, budget, or creative requirements. - */ - post: operations['tactic_update']; - }; - '/tactic-delete': { - /** - * Delete tactic - * @description Delete a tactic and all associated media buys. - */ - post: operations['tactic_delete']; - }; - '/tactic-get': { - /** - * Get tactic - * @description Get detailed information about a specific tactic. - */ - post: operations['tactic_get']; - }; - '/tactic-list': { - /** - * List tactics - * @description List all tactics with optional filtering by brand agent or campaign. - */ - post: operations['tactic_list']; - }; - '/tactic-link-campaign': { - /** - * Link tactic to campaign - * @description Link a tactic to a campaign. - */ - post: operations['tactic_link_campaign']; - }; - '/tactic-unlink-campaign': { - /** - * Unlink tactic from campaign - * @description Unlink a tactic from a campaign. - */ - post: operations['tactic_unlink_campaign']; - }; - '/webhook-register': { - /** - * Register webhook - * @description Register a webhook to receive real-time notifications about events. - */ - post: operations['webhook_register']; - }; - '/webhook-list': { - /** - * List webhooks - * @description List all registered webhooks. - */ - post: operations['webhook_list']; - }; - '/webhook-delete': { - /** - * Delete webhook - * @description Delete a registered webhook. - */ - post: operations['webhook_delete']; - }; - '/service-token-create': { - /** - * Create service token - * @description Create a new service token for API authentication. Returns the full token which should be stored securely as it cannot be retrieved later. - */ - post: operations['service_token_create']; - }; - '/service-token-list': { - /** - * List service tokens - * @description List all service tokens for the authenticated customer. Secrets are never returned, only metadata. - */ - post: operations['service_token_list']; - }; - '/service-token-get': { - /** - * Get service token - * @description Get detailed information about a specific service token. The secret is never returned. - */ - post: operations['service_token_get']; - }; - '/service-token-update': { - /** - * Update service token - * @description Update a service token. Only name, description, and expiration can be modified. - */ - post: operations['service_token_update']; - }; - '/service-token-archive': { - /** - * Archive service token - * @description Archive (soft delete) a service token. This immediately invalidates the token for authentication. - */ - post: operations['service_token_archive']; - }; - '/customer-get': { - /** - * Get customer info - * @description Get detailed information about a customer from the core database. - */ - post: operations['customer_get']; - }; - '/customer-get-seats': { - /** - * Get customer seats - * @description Get all seats associated with a customer from the core database. - */ - post: operations['customer_get_seats']; - }; -} - -export type webhooks = Record; - -export interface components { - schemas: { - ListChannelsInput: Record; - GetCustomerInput: { - /** - * @description The unique identifier of the customer to retrieve. If not provided, uses the authenticated users customer ID. - * @example 100 - */ - customerId?: number; - }; - GetCustomerSeatsInput: { - /** - * @description The unique identifier of the customer whose seats to retrieve. If not provided, uses the authenticated users customer ID. - * @example 100 - */ - customerId?: number; - }; - SyncSalesAgentsInput: { - /** @example example_id_123 */ - creativeId: string; - }; - ListCountriesInput: Record; - ListLanguagesInput: Record; - CreateMediaBuyInput: { - /** @example 100 */ - tacticId: number; - /** @example example_id_123 */ - agentId: string; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** @example [] */ - products: { - mediaProductId: string; - budgetAmount: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creatives?: { - creative_id: string; - name: string; - format_id: - | string - | { - agent_url: string; - id: string; - }; - assets?: { - [key: string]: { - url: string; - width?: number; - height?: number; - }; - }; - click_url?: string; - }[]; - }[]; - /** @example [] */ - creatives?: { - creative_id: string; - name: string; - format_id: - | string - | { - agent_url: string; - id: string; - }; - assets?: { - [key: string]: { - url: string; - width?: number; - height?: number; - }; - }; - click_url?: string; - }[]; - }; - UpdateMediaBuyInput: { - /** @example example_id_123 */ - mediaBuyId: string; - /** @example Example Name */ - name?: string; - /** @example string */ - description?: string; - /** - * @example DRAFT - * @enum {string} - */ - status?: - | 'DRAFT' - | 'PENDING_APPROVAL' - | 'ACTIVE' - | 'PAUSED' - | 'COMPLETED' - | 'FAILED' - | 'REJECTED'; - /** @example [] */ - creativeIds?: string[]; - /** @example [] */ - packages?: { - packageId: string; - creativeIds: string[]; - }[]; - }; - DeleteMediaBuyInput: { - /** @example example_id_123 */ - mediaBuyId: string; - /** @example true */ - confirm: boolean; - }; - ExecuteMediaBuyInput: { - /** @example example_id_123 */ - mediaBuyId: string; - }; - GetMediaBuyInput: { - /** @example example_id_123 */ - mediaBuyId: string; - }; - ListMediaBuysInput: { - /** @example 100 */ - tacticId?: number; - /** - * @example DRAFT - * @enum {string} - */ - status?: - | 'DRAFT' - | 'PENDING_APPROVAL' - | 'ACTIVE' - | 'PAUSED' - | 'COMPLETED' - | 'FAILED' - | 'REJECTED'; - /** @example 100 */ - take?: number; - /** @example 100 */ - skip?: number; - }; - ValidateMediaBuyBudgetInput: { - /** @example 100 */ - tacticId: number; - /** @example 100 */ - newBudgetAmount: number; - }; - ListNotificationsInput: { - /** @example 100 */ - brandAgentId?: number; - /** @example example_id_123 */ - campaignId?: string; - /** @example example_id_123 */ - creativeId?: string; - /** @example example_id_123 */ - tacticId?: string; - /** @example [] */ - types?: string[]; - /** @example true */ - unreadOnly?: boolean; - /** @example 100 */ - limit?: number; - /** @example 100 */ - offset?: number; - }; - MarkNotificationReadInput: { - /** @example example_id_123 */ - notificationId: string; - }; - MarkNotificationAcknowledgedInput: { - /** @example example_id_123 */ - notificationId: string; - }; - MarkAllNotificationsReadInput: Record; - DiscoverProductsInput: { - /** - * @description Natural language description of campaign requirements (e.g., "Launch $50k luxury electric vehicle awareness campaign targeting 10M affluent buyers, 60 days, max CPM $15") - * @example string - */ - brief: string; - /** - * Format: uri - * @description Valid URL for the brand (e.g., company website https://example.com or hosted brand manifest JSON) - * @example https://example.com - */ - brandManifestUrl: string; - /** @description Structured filters for product discovery */ - filters?: { - /** @enum {string} */ - deliveryType?: 'guaranteed' | 'non_guaranteed'; - /** @description Filter for fixed price vs auction products */ - isFixedPrice?: boolean; - /** @description Filter by format types */ - formatTypes?: ('video' | 'display' | 'audio')[]; - /** @description Only return products accepting IAB standard formats */ - standardFormatsOnly?: boolean; - /** @description Minimum exposures/impressions needed for measurement validity */ - minExposures?: number; - }; - /** - * @description Optional: Query a specific sales agent by ID. If not provided, queries all active sales agents. - * @example example_id_123 - */ - agentId?: string; - /** - * @description Whether to save discovered products for future use (default: true) - * @example true - */ - saveToDatabase?: boolean; - }; - SaveProductInput: { - /** @example example_id_123 */ - productId: string; - /** @example Example Name */ - name: string; - /** @example string */ - description: string; - /** @example example_id_123 */ - publisherId: string; - /** @example Example Name */ - publisherName: string; - /** - * @example guaranteed - * @enum {string} - */ - deliveryType: 'guaranteed' | 'non_guaranteed'; - /** - * @example premium - * @enum {string} - */ - inventoryType: 'premium' | 'run_of_site' | 'targeted_package'; - creativeFormats?: - | string[] - | { - agent_url: string; - id: string; - }[]; - /** - * @example auction - * @enum {string} - */ - pricingModel: 'auction' | 'fixed_cpm'; - /** @example 100 */ - fixedCpm?: number; - /** @example 100 */ - floorCpm?: number; - /** @example 100 */ - targetCpm?: number; - /** @example [] */ - pricingOptions?: { - [key: string]: unknown; - }[]; - /** @example [] */ - supportedTargeting?: string[]; - /** @example example_id_123 */ - adcpAgentId?: string; - }; - ListProductsInput: { - /** @example 100 */ - take?: number; - /** @example 100 */ - skip?: number; - }; - SyncProductsInput: { - /** @example example_id_123 */ - sourceId: string; - }; - GetAgentInput: { - /** - * @description The agent ID to retrieve - * @example example_id_123 - */ - agentId: string; - }; - ListAgentsInput: { - /** - * @description Filter by agent type (SALES or OUTCOME) - * @example SALES - * @enum {string} - */ - type?: 'SALES' | 'OUTCOME'; - /** - * @description Filter by status (PENDING, ACTIVE, DISABLED) - * @example PENDING - * @enum {string} - */ - status?: 'PENDING' | 'ACTIVE' | 'DISABLED'; - /** - * @description Filter by organization ID - * @example example_id_123 - */ - organizationId?: string; - /** - * @description Filter by relationship (SELF = owned by you, SCOPE3 = Scope3-provided, MARKETPLACE = third-party marketplace agents) - * @example SELF - * @enum {string} - */ - relationship?: 'SELF' | 'SCOPE3' | 'MARKETPLACE'; - /** - * @description Filter by agent name (partial match) - * @example Example Name - */ - name?: string; - }; - RegisterAgentInput: { - /** - * @description The type of agent to register - * @example SALES - * @enum {string} - */ - type: 'SALES' | 'OUTCOME'; - /** - * @description Agent name - * @example Example Name - */ - name: string; - /** - * @description Agent description - * @example string - */ - description?: string; - /** - * Format: uri - * @description Agent endpoint URL - * @example https://example.com - */ - endpointUrl: string; - /** - * @description Protocol used by the agent (MCP or A2A) - * @example MCP - * @enum {string} - */ - protocol: 'MCP' | 'A2A'; - /** - * @description Authentication type - * @example API_KEY - * @enum {string} - */ - authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH' | 'JWT'; - /** - * @description Organization ID - * @example example_id_123 - */ - organizationId?: string; - /** @description Authentication configuration object */ - auth?: - | { - /** @enum {string} */ - type: 'jwt'; - privateKey: string; - issuer: string; - subject: string; - keyId: string; - scope: string; - /** Format: uri */ - tokenEndpointUrl: string; - /** Format: uri */ - audienceUrl: string; - /** @enum {string} */ - algorithm?: 'ES256' | 'RS256'; - environment?: string; - } - | { - /** @enum {string} */ - type: 'bearer' | 'apikey' | 'api_key'; - token: string; - } - | { - /** @enum {string} */ - type: 'oauth' | 'oauth2'; - token: string; - } - | Record; - }; - UnregisterAgentInput: { - /** - * @description The agent ID to unregister - * @example example_id_123 - */ - agentId: string; - }; - UpdateAgentInput: { - /** - * @description The agent ID to update - * @example example_id_123 - */ - agentId: string; - /** - * @description New agent name - * @example Example Name - */ - name?: string; - /** - * @description New agent description - * @example string - */ - description?: string; - /** - * Format: uri - * @description New endpoint URL - * @example https://example.com - */ - endpointUrl?: string; - /** - * @description New protocol - * @example MCP - * @enum {string} - */ - protocol?: 'MCP' | 'A2A'; - /** - * @description New authentication type - * @example API_KEY - * @enum {string} - */ - authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH' | 'JWT'; - /** @description New authentication configuration */ - auth?: - | { - /** @enum {string} */ - type: 'jwt'; - privateKey: string; - issuer: string; - subject: string; - keyId: string; - scope: string; - /** Format: uri */ - tokenEndpointUrl: string; - /** Format: uri */ - audienceUrl: string; - /** @enum {string} */ - algorithm?: 'ES256' | 'RS256'; - environment?: string; - } - | { - /** @enum {string} */ - type: 'bearer' | 'apikey' | 'api_key'; - token: string; - } - | { - /** @enum {string} */ - type: 'oauth' | 'oauth2'; - token: string; - } - | Record; - }; - CreateTacticInput: { - /** @example example_id_123 */ - campaignId: string; - /** @example Example Name */ - name: string; - /** @example string */ - prompt?: string; - /** @example [] */ - channelCodes?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; - /** @example [] */ - countryCodes?: string[]; - /** - * @description Language codes - * @example [] - */ - languages?: string[]; - /** @example [] */ - availableBrandStandards?: { - id: number; - name: string; - }[]; - /** @example [] */ - availableBrandStory?: { - id: number; - name: string; - }[]; - }; - UpdateTacticInput: { - /** @example 100 */ - tacticId: number; - /** @example Example Name */ - name?: string; - /** @example string */ - prompt?: string; - /** @example [] */ - channelCodes?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; - /** @example [] */ - countryCodes?: string[]; - /** @example [] */ - availableBrandStandards?: { - id: number; - name: string; - }[]; - /** @example [] */ - availableBrandStory?: { - id: number; - name: string; - }[]; - }; - DeleteTacticInput: { - /** @example 100 */ - tacticId: number; - /** @example true */ - confirm: boolean; - }; - GetTacticInput: { - /** @example 100 */ - tacticId: number; - }; - ListTacticsInput: { - /** @example example_id_123 */ - campaignId?: string; - /** @example 100 */ - take?: number; - /** @example 100 */ - skip?: number; - }; - LinkCampaignToTacticInput: { - /** @example 100 */ - tacticId: number; - /** @example example_id_123 */ - campaignId: string; - }; - UnlinkCampaignFromTacticInput: { - /** @example 100 */ - tacticId: number; - /** @example example_id_123 */ - campaignId: string; - }; - RegisterWebhookInput: { - /** @example 100 */ - brandAgentId?: number; - endpoint: { - /** Format: uri */ - url: string; - /** @enum {string} */ - method: 'POST' | 'PUT'; - headers?: { - [key: string]: string; - }; - authentication?: { - /** @enum {string} */ - type: 'bearer' | 'basic' | 'hmac'; - credentials: string; - }; - }; - /** @example [] */ - eventTypes: string[]; - filters?: { - campaigns?: string[]; - tactics?: string[]; - creatives?: string[]; - mediaBuys?: string[]; - metrics?: string[]; - /** @enum {string} */ - minSeverity?: 'info' | 'warning' | 'critical'; - }; - retryPolicy?: { - maxRetries?: number; - backoffMultiplier?: number; - maxBackoffSeconds?: number; - }; - }; - ListWebhooksInput: { - /** @example 100 */ - take?: number; - /** @example 100 */ - skip?: number; - }; - DeleteWebhookInput: { - /** @example example_id_123 */ - webhookId: string; - }; - CreateServiceTokenInput: { - /** - * @description Human-readable name for the service token - * @example Example Name - */ - name: string; - /** - * @description Optional description of the token purpose and usage - * @example string - */ - description?: string; - /** - * @description Number of days until token expiration (max 365). If not provided, token does not expire - * @example 100 - */ - expiresInDays?: number; - /** - * @description Token scope: CUSTOMER (full customer access) or SEAT (scoped to specific seat) - * @default CUSTOMER - * @enum {string} - */ - scope?: 'CUSTOMER' | 'SEAT'; - /** - * @description Seat name (required when scope is SEAT). The seat will be looked up for the customer. - * @example Example Name - */ - seatName?: string; - }; - UpdateServiceTokenInput: { - /** - * Format: int64 - * @description The unique identifier of the service token to update - * @example 100 - */ - id: number; - /** - * @description Updated human-readable name for the service token - * @example Example Name - */ - name?: string; - /** - * @description Updated description of the token purpose and usage - * @example string - */ - description?: string; - /** - * @description Number of days to extend expiration from now (max 365). Updates the expiresAt timestamp - * @example 100 - */ - expiresInDays?: number; - }; - ArchiveServiceTokenInput: { - /** - * Format: int64 - * @description The unique identifier of the service token to archive - * @example 100 - */ - id: number; - }; - GetServiceTokenInput: { - /** - * Format: int64 - * @description The unique identifier of the service token to retrieve - * @example 100 - */ - id: number; - /** - * @description Whether to fetch the access_client_secret from Google Secret Manager. Defaults to false for security - * @default false - */ - includeSecret?: boolean; - }; - ListServiceTokensInput: { - /** - * @description Whether to include archived tokens in the response - * @default false - */ - includeArchived?: boolean; - /** - * Format: int64 - * @description Filter tokens by seat ID - * @example 100 - */ - seatId?: number; - /** - * Format: int64 - * @description Filter tokens by user ID - * @example 100 - */ - userId?: number; - }; - MediaBuyGet: { - /** @example example_id_123 */ - id: string; - /** @example 100 */ - tacticId: number; - /** @example 100 */ - customerId: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** @example [] */ - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - /** @example string */ - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - TacticGet: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - prompt?: string; - /** @example [] */ - campaignIds?: string[]; - /** @example [] */ - channelCodes: string[]; - /** @example [] */ - countryCodes: string[]; - /** @example 100 */ - mediaBuyCount?: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - }; - MCPContent: { - /** - * @example text - * @enum {string} - */ - type: 'text'; - /** @example string */ - text: string; - }; - /** @description Bad request error response */ - BadRequest: { - /** @example string */ - error: string; - /** @example string */ - message?: string; - }; - /** @description Unauthorized error response */ - Unauthorized: { - /** @example string */ - error: string; - /** @example string */ - message?: string; - }; - /** @description Internal server error response */ - InternalError: { - /** @example string */ - error: string; - /** @example string */ - message?: string; - }; - ChannelList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - channel: string; - displayName: string; - }[]; - }; - GetCustomerOutput: { - /** - * @description Unique identifier for the customer - * @example 100 - */ - id: number; - /** - * @description Company name - * @example string - */ - company: string; - /** - * @description Customer display name - * @example Example Name - */ - name: string; - /** - * @description Whether the customer is currently active - * @example true - */ - active: boolean; - /** - * Format: date-time - * @description ISO 8601 timestamp when the customer was created - * @example string - */ - createdAt: string; - }; - GetCustomerSeatsOutput: { - /** - * @description The customer ID these seats belong to - * @example 100 - */ - customerId: number; - /** - * @description Array of seats belonging to the customer - * @example [] - */ - seats: { - /** @description Unique identifier for the seat */ - id: string; - /** @description Seat display name */ - name: string; - /** @description Customer ID that owns this seat */ - customerId: number; - /** @description Whether the seat is currently active */ - active: boolean; - }[]; - /** - * @description Total number of seats returned - * @example 100 - */ - count: number; - }; - CreativeSyncSalesAgents: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - creativeId: string; - /** @example example_id_123 */ - campaignId?: string; - }; - CountryList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - key: string; - displayName: string; - }[]; - }; - LanguageList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - key: string; - displayName: string; - }[]; - }; - MediaBuyDelete: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - id: string; - }; - MediaBuyExecute: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - mediaBuyId: string; - /** @example string */ - status: string; - /** @example example_id_123 */ - adcpMediaBuyId?: string; - /** @example string */ - adcpStatus?: string; - }; - MediaBuyList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: components['schemas']['MediaBuyGetOutput'][]; - }; - MediaBuyValidateBudget: { - /** @example true */ - valid: boolean; - /** @example string */ - message?: string; - }; - NotificationsList: { - /** @example 100 */ - total: number; - /** @example true */ - hasMore: boolean; - /** @example [] */ - items: { - id: string; - type: string; - data: { - [key: string]: unknown; - }; - read: boolean; - acknowledged: boolean; - /** Format: date-time */ - createdAt: string; - }[]; - }; - NotificationsMarkRead: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - notificationId: string; - }; - NotificationsMarkAcknowledged: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - notificationId: string; - }; - NotificationsMarkAllRead: { - /** @example true */ - success: boolean; - /** @example 100 */ - count: number; - }; - MediaProductDiscover: { - /** @example true */ - success: boolean; - /** @example 100 */ - productsFound: number; - /** @example 100 */ - productsSaved: number; - /** @example 100 */ - successfulAgents: number; - /** @example 100 */ - failedAgents: number; - /** @example [] */ - products: { - productId: string; - name: string; - publisherName: string; - salesAgentId?: string; - salesAgentName?: string; - /** @enum {string} */ - deliveryType: 'guaranteed' | 'non_guaranteed'; - /** @enum {string} */ - inventoryType: 'premium' | 'run_of_site' | 'targeted_package'; - creativeFormats?: - | string[] - | { - agent_url: string; - id: string; - }[]; - fixedCpm?: number; - floorCpm?: number; - targetCpm?: number; - }[]; - }; - MediaProductSave: { - /** @example example_id_123 */ - id: string; - /** @example example_id_123 */ - productId: string; - /** @example Example Name */ - name: string; - /** @example example_id_123 */ - publisherId: string; - /** @example Example Name */ - publisherName: string; - /** @example 100 */ - customerId: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - MediaProductList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - id: string; - productId: string; - name: string; - salesAgent?: string; - salesAgentId?: string; - salesAgentName?: string; - /** @enum {string} */ - deliveryType: 'guaranteed' | 'non_guaranteed'; - format?: string; - creativeFormats?: - | string[] - | { - agent_url: string; - id: string; - }[]; - }[]; - }; - MediaProductSync: { - /** @example true */ - success: boolean; - /** @example 100 */ - productsSaved: number; - }; - AgentGet: - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - authenticationType: string; - description?: string; - organizationId?: string; - registeredBy?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - } - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - authenticationType: string; - description?: string; - organizationId?: string; - registeredBy?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - customerAccountCount: number; - }; - AgentList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: ( - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - } - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - customerAccountCount: number; - } - )[]; - }; - AgentRegister: { - /** @example example_id_123 */ - agentId: string; - /** @example Example Name */ - name: string; - /** - * @example SALES - * @enum {string} - */ - type: 'SALES' | 'OUTCOME'; - /** @example string */ - status: string; - /** @example https://example.com */ - endpointUrl: string; - }; - AgentUnregister: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - agentId: string; - /** - * @example SALES - * @enum {string} - */ - type: 'SALES' | 'OUTCOME'; - }; - AgentUpdate: { - /** @example example_id_123 */ - agentId: string; - /** @example Example Name */ - name: string; - /** - * @example SALES - * @enum {string} - */ - type: 'SALES' | 'OUTCOME'; - /** @example string */ - status: string; - }; - TacticCreate: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - prompt?: string; - /** @example example_id_123 */ - campaignId: string; - /** @example [] */ - channelCodes: string[]; - /** @example [] */ - countryCodes: string[]; - /** - * Format: date-time - * @example string - */ - createdAt: string; - }; - TacticDelete: { - /** @example true */ - success: boolean; - /** @example 100 */ - tacticId: number; - }; - TacticList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: components['schemas']['TacticGetOutput'][]; - }; - TacticLinkCampaign: { - /** @example true */ - success: boolean; - /** @example 100 */ - tacticId: number; - /** @example example_id_123 */ - campaignId: string; - }; - TacticUnlinkCampaign: { - /** @example true */ - success: boolean; - /** @example 100 */ - tacticId: number; - /** @example example_id_123 */ - campaignId: string; - }; - WebhookRegister: { - /** @example example_id_123 */ - id: string; - /** @example 100 */ - brandAgentId?: number; - endpoint: { - url: string; - method: string; - authenticationType?: string; - }; - /** @example [] */ - eventTypes: string[]; - filters?: { - campaigns?: string[]; - tactics?: string[]; - creatives?: string[]; - mediaBuys?: string[]; - metrics?: string[]; - minSeverity?: string; - }; - retryPolicy: { - maxRetries: number; - backoffMultiplier: number; - maxBackoffSeconds: number; - }; - /** @example string */ - status: string; - testResult: { - success: boolean; - statusCode?: number; - error?: string; - }; - }; - WebhookList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - id: string; - status: string; - endpoint: { - url: string; - method: string; - authenticationType?: string; - }; - eventTypes: string[]; - brandAgentId?: number; - failureCount: number; - /** Format: date-time */ - lastSuccess?: string | null; - /** Format: date-time */ - lastFailure?: string | null; - /** Format: date-time */ - createdAt: string; - }[]; - }; - WebhookDelete: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - webhookId: string; - }; - CreateServiceTokenOutput: { - /** - * Format: int64 - * @description Unique identifier for the service token - * @example 100 - */ - id: number; - /** - * @description Customer ID that owns this token - * @example 100 - */ - customerId: number; - /** - * Format: int64 - * @description Seat ID if token is scoped to a specific seat - * @example 100 - */ - seatId?: number; - /** - * Format: int64 - * @description User ID if token is scoped to a specific user - * @example 100 - */ - userId?: number; - /** - * @description Optional organization identifier for scoping the token - * @example example_id_123 - */ - organizationId?: string; - /** - * @description Human-readable name of the token - * @example Example Name - */ - name: string; - /** - * @description Description of the token purpose - * @example string - */ - description?: string; - /** - * @description The public client ID portion of the token credentials (safe to log) - * @example example_id_123 - */ - accessClientId: string; - /** - * @description The secret portion of the token credentials. ONLY returned on creation, never retrievable again! - * @example string - */ - accessClientSecret: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token expires, if set - * @example string - */ - expiresAt?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was created - * @example string - */ - createdAt: string; - }; - UpdateServiceTokenOutput: { - /** - * Format: int64 - * @description Unique identifier for the service token - * @example 100 - */ - id: number; - /** - * @description Updated human-readable name of the token - * @example Example Name - */ - name: string; - /** - * @description Updated description of the token purpose - * @example string - */ - description?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token expires, if updated - * @example string - */ - expiresAt?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was last updated - * @example string - */ - updatedAt: string; - }; - ArchiveServiceTokenOutput: { - /** - * Format: int64 - * @description Unique identifier for the archived token - * @example 100 - */ - id: number; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was archived - * @example string - */ - archivedAt: string; - }; - GetServiceTokenOutput: { - /** - * Format: int64 - * @description Unique identifier for the service token - * @example 100 - */ - id: number; - /** - * @description Customer ID that owns this token - * @example 100 - */ - customerId: number; - /** - * Format: int64 - * @description Seat ID if token is scoped to a specific seat - * @example 100 - */ - seatId?: number; - /** - * Format: int64 - * @description User ID if token is scoped to a specific user - * @example 100 - */ - userId?: number; - /** - * @description Optional organization identifier for scoping the token - * @example example_id_123 - */ - organizationId?: string; - /** - * @description Human-readable name of the token - * @example Example Name - */ - name: string; - /** - * @description Description of the token purpose - * @example string - */ - description?: string; - /** - * @description The public client ID portion of the token credentials (safe to log) - * @example example_id_123 - */ - accessClientId: string; - /** - * @description The secret portion of the token credentials. Only included if includeSecret=true was passed - * @example string - */ - accessClientSecret?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token expires, if set - * @example string - */ - expiresAt?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was created - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was last updated - * @example string - */ - updatedAt: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was archived, if archived - * @example string - */ - archivedAt?: string; - }; - ListServiceTokensOutput: { - /** - * @description Array of service tokens. Note: accessClientSecret is never included in list responses - * @example [] - */ - tokens: { - /** - * Format: int64 - * @description Unique identifier for the service token - */ - id: number; - /** @description Customer ID that owns this token */ - customerId: number; - /** - * Format: int64 - * @description Seat ID if token is scoped to a specific seat - */ - seatId?: number; - /** @description Seat name if token is scoped to a specific seat */ - seatName?: string; - /** - * Format: int64 - * @description User ID if token is scoped to a specific user - */ - userId?: number; - /** @description Optional organization identifier for scoping the token */ - organizationId?: string; - /** @description Human-readable name of the token */ - name: string; - /** @description Description of the token purpose */ - description?: string; - /** @description The public client ID portion of the token credentials (safe to log) */ - accessClientId: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token expires, if set - */ - expiresAt?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was created - */ - createdAt: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was last updated - */ - updatedAt: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was archived, if archived - */ - archivedAt?: string; - }[]; - /** - * @description Total number of tokens returned - * @example 100 - */ - count: number; - }; - MediaBuyGetOutput: { - /** @example example_id_123 */ - id: string; - /** @example 100 */ - tacticId: number; - /** @example 100 */ - customerId: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** @example [] */ - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - /** @example string */ - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - TacticGetOutput: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - prompt?: string; - /** @example [] */ - campaignIds?: string[]; - /** @example [] */ - channelCodes: string[]; - /** @example [] */ - countryCodes: string[]; - /** @example 100 */ - mediaBuyCount?: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - }; - MediaBuyCreate: { - /** @example example_id_123 */ - id: string; - /** @example 100 */ - tacticId: number; - /** @example 100 */ - customerId: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** @example [] */ - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - /** @example string */ - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - MediaBuyUpdate: { - /** @example example_id_123 */ - id: string; - /** @example 100 */ - tacticId: number; - /** @example 100 */ - customerId: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** @example [] */ - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - /** @example string */ - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - TacticUpdate: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - prompt?: string; - /** @example [] */ - campaignIds?: string[]; - /** @example [] */ - channelCodes: string[]; - /** @example [] */ - countryCodes: string[]; - /** @example 100 */ - mediaBuyCount?: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; -} - -export type $defs = Record; - -export type external = Record; - -export interface operations { - /** - * Initialize MCP session - * @description Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as a UUID and included in the mcp-session-id header for all subsequent requests. - */ - mcp_initialize: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Generate a new UUID for session initialization. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - jsonrpc: '2.0'; - id: string | number; - /** @enum {string} */ - method: 'initialize'; - params: { - /** @example 2024-11-05 */ - protocolVersion: string; - capabilities: Record; - clientInfo: { - name: string; - version: string; - }; - }; - }; - }; - }; - responses: { - /** @description Session initialized successfully */ - 200: { - content: { - 'application/json': { - /** @enum {string} */ - jsonrpc?: '2.0'; - id?: string | number; - result?: { - protocolVersion?: string; - capabilities?: Record; - serverInfo?: { - name?: string; - version?: string; - }; - }; - }; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - }; - }; - /** - * List channels - * @description List all available advertising channels and platforms. - */ - channel_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for channel_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "channel_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'channel_list'; - arguments: components['schemas']['ListChannelsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['ChannelList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List countries - * @description Get all available countries for targeting. Use this to get valid country codes before creating brand agents. - */ - country_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for country_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "country_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'country_list'; - arguments: components['schemas']['ListCountriesInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CountryList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List languages - * @description Get all available languages for targeting. Use this to get valid language codes before creating brand stories. - */ - language_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for language_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "language_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'language_list'; - arguments: components['schemas']['ListLanguagesInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['LanguageList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Sync creatives to sales agents - * @description Synchronize creatives to connected sales agents (DSPs, publisher platforms). - */ - creative_sync_sales_agents: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for creative_sync_sales_agents */ - requestBody: { - content: { - /** - * @example { - * "tool": "creative_sync_sales_agents", - * "arguments": { - * "creativeId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'creative_sync_sales_agents'; - arguments: components['schemas']['SyncSalesAgentsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeSyncSalesAgents']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create media buy - * @description Create a new media buy with budget, targeting, and creative specifications. - */ - media_buy_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_buy_create */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_buy_create", - * "arguments": { - * "tacticId": 100, - * "agentId": "example_id_123", - * "name": "Example Name", - * "products": [] - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_create'; - arguments: components['schemas']['CreateMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update media buy - * @description Update an existing media buy with new budget, targeting, or creative assignments. - */ - media_buy_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_buy_update */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_buy_update", - * "arguments": { - * "mediaBuyId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_update'; - arguments: components['schemas']['UpdateMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete media buy - * @description Delete a media buy and cancel any active placements. - */ - media_buy_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_buy_delete */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_buy_delete", - * "arguments": { - * "mediaBuyId": "example_id_123", - * "confirm": true - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_delete'; - arguments: components['schemas']['DeleteMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Execute media buy - * @description Execute a media buy, sending it to the configured sales agents for placement. - */ - media_buy_execute: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_buy_execute */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_buy_execute", - * "arguments": { - * "mediaBuyId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_execute'; - arguments: components['schemas']['ExecuteMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyExecute']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get media buy - * @description Get detailed information about a specific media buy. - */ - media_buy_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_buy_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_buy_get", - * "arguments": { - * "mediaBuyId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_get'; - arguments: components['schemas']['GetMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List media buys - * @description List all media buys with optional filtering by brand agent, campaign, or status. - */ - media_buy_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_buy_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_buy_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_list'; - arguments: components['schemas']['ListMediaBuysInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Validate media buy budget - * @description Validate a media buy budget against campaign constraints and available funds. - */ - media_buy_validate_budget: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_buy_validate_budget */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_buy_validate_budget", - * "arguments": { - * "tacticId": 100, - * "newBudgetAmount": 100 - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_validate_budget'; - arguments: components['schemas']['ValidateMediaBuyBudgetInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyValidateBudget']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List notifications - * @description List notifications for the authenticated user with optional filtering by status. - */ - notifications_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for notifications_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "notifications_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'notifications_list'; - arguments: components['schemas']['ListNotificationsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['NotificationsList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Mark notification as read - * @description Mark a specific notification as read. - */ - notifications_mark_read: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for notifications_mark_read */ - requestBody: { - content: { - /** - * @example { - * "tool": "notifications_mark_read", - * "arguments": { - * "notificationId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'notifications_mark_read'; - arguments: components['schemas']['MarkNotificationReadInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['NotificationsMarkRead']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Mark notification as acknowledged - * @description Mark a specific notification as acknowledged. - */ - notifications_mark_acknowledged: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for notifications_mark_acknowledged */ - requestBody: { - content: { - /** - * @example { - * "tool": "notifications_mark_acknowledged", - * "arguments": { - * "notificationId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'notifications_mark_acknowledged'; - arguments: components['schemas']['MarkNotificationAcknowledgedInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['NotificationsMarkAcknowledged']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Mark all notifications as read - * @description Mark all notifications for the authenticated user as read. - */ - notifications_mark_all_read: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for notifications_mark_all_read */ - requestBody: { - content: { - /** - * @example { - * "tool": "notifications_mark_all_read", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'notifications_mark_all_read'; - arguments: components['schemas']['MarkAllNotificationsReadInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['NotificationsMarkAllRead']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Discover media products - * @description Discover available media products from connected sales agents based on targeting criteria. - */ - media_product_discover: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_product_discover */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_product_discover", - * "arguments": { - * "brief": "string", - * "brandManifestUrl": "https://example.com" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_product_discover'; - arguments: components['schemas']['DiscoverProductsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaProductDiscover']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Save media product - * @description Save a discovered media product for future use in media buys. - */ - media_product_save: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_product_save */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_product_save", - * "arguments": { - * "productId": "example_id_123", - * "name": "Example Name", - * "description": "string", - * "publisherId": "example_id_123", - * "publisherName": "Example Name", - * "deliveryType": "guaranteed", - * "inventoryType": "premium", - * "pricingModel": "auction" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_product_save'; - arguments: components['schemas']['SaveProductInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaProductSave']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List media products - * @description List saved media products with optional filtering. - */ - media_product_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_product_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_product_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_product_list'; - arguments: components['schemas']['ListProductsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaProductList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Sync media products - * @description Synchronize media product catalog from connected sales agents. - */ - media_product_sync: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_product_sync */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_product_sync", - * "arguments": { - * "sourceId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_product_sync'; - arguments: components['schemas']['SyncProductsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaProductSync']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get agent - * @description Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the agent ID. - */ - agent_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for agent_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "agent_get", - * "arguments": { - * "agentId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'agent_get'; - arguments: components['schemas']['GetAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentGet']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List agents - * @description List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - */ - agent_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for agent_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "agent_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'agent_list'; - arguments: components['schemas']['ListAgentsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Register agent - * @description Register a new agent for media buying (SALES type) or outcome optimization (OUTCOME type). - */ - agent_register: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for agent_register */ - requestBody: { - content: { - /** - * @example { - * "tool": "agent_register", - * "arguments": { - * "type": "SALES", - * "name": "Example Name", - * "endpointUrl": "https://example.com", - * "protocol": "MCP" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'agent_register'; - arguments: components['schemas']['RegisterAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentRegister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Unregister agent - * @description Unregister an agent and disconnect it from the platform. Type is automatically inferred from the agent ID. - */ - agent_unregister: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for agent_unregister */ - requestBody: { - content: { - /** - * @example { - * "tool": "agent_unregister", - * "arguments": { - * "agentId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'agent_unregister'; - arguments: components['schemas']['UnregisterAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentUnregister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update agent - * @description Update agent configuration and credentials. Type is automatically inferred from the agent ID. - */ - agent_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for agent_update */ - requestBody: { - content: { - /** - * @example { - * "tool": "agent_update", - * "arguments": { - * "agentId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'agent_update'; - arguments: components['schemas']['UpdateAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentUpdate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create tactic - * @description Create a new tactic defining how to achieve campaign objectives. - */ - tactic_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for tactic_create */ - requestBody: { - content: { - /** - * @example { - * "tool": "tactic_create", - * "arguments": { - * "campaignId": "example_id_123", - * "name": "Example Name" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'tactic_create'; - arguments: components['schemas']['CreateTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticCreate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update tactic - * @description Update an existing tactic with new targeting, budget, or creative requirements. - */ - tactic_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for tactic_update */ - requestBody: { - content: { - /** - * @example { - * "tool": "tactic_update", - * "arguments": { - * "tacticId": 100 - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'tactic_update'; - arguments: components['schemas']['UpdateTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete tactic - * @description Delete a tactic and all associated media buys. - */ - tactic_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for tactic_delete */ - requestBody: { - content: { - /** - * @example { - * "tool": "tactic_delete", - * "arguments": { - * "tacticId": 100, - * "confirm": true - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'tactic_delete'; - arguments: components['schemas']['DeleteTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get tactic - * @description Get detailed information about a specific tactic. - */ - tactic_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for tactic_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "tactic_get", - * "arguments": { - * "tacticId": 100 - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'tactic_get'; - arguments: components['schemas']['GetTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List tactics - * @description List all tactics with optional filtering by brand agent or campaign. - */ - tactic_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for tactic_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "tactic_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'tactic_list'; - arguments: components['schemas']['ListTacticsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Link tactic to campaign - * @description Link a tactic to a campaign. - */ - tactic_link_campaign: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for tactic_link_campaign */ - requestBody: { - content: { - /** - * @example { - * "tool": "tactic_link_campaign", - * "arguments": { - * "tacticId": 100, - * "campaignId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'tactic_link_campaign'; - arguments: components['schemas']['LinkCampaignToTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticLinkCampaign']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Unlink tactic from campaign - * @description Unlink a tactic from a campaign. - */ - tactic_unlink_campaign: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for tactic_unlink_campaign */ - requestBody: { - content: { - /** - * @example { - * "tool": "tactic_unlink_campaign", - * "arguments": { - * "tacticId": 100, - * "campaignId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'tactic_unlink_campaign'; - arguments: components['schemas']['UnlinkCampaignFromTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticUnlinkCampaign']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Register webhook - * @description Register a webhook to receive real-time notifications about events. - */ - webhook_register: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for webhook_register */ - requestBody: { - content: { - /** - * @example { - * "tool": "webhook_register", - * "arguments": { - * "endpoint": { - * "url": "https://example.com", - * "method": "POST" - * }, - * "eventTypes": [] - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'webhook_register'; - arguments: components['schemas']['RegisterWebhookInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['WebhookRegister']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List webhooks - * @description List all registered webhooks. - */ - webhook_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for webhook_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "webhook_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'webhook_list'; - arguments: components['schemas']['ListWebhooksInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['WebhookList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete webhook - * @description Delete a registered webhook. - */ - webhook_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for webhook_delete */ - requestBody: { - content: { - /** - * @example { - * "tool": "webhook_delete", - * "arguments": { - * "webhookId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'webhook_delete'; - arguments: components['schemas']['DeleteWebhookInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['WebhookDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create service token - * @description Create a new service token for API authentication. Returns the full token which should be stored securely as it cannot be retrieved later. - */ - service_token_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_create */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_create", - * "arguments": { - * "name": "Example Name" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_create'; - arguments: components['schemas']['CreateServiceTokenInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreateServiceTokenOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List service tokens - * @description List all service tokens for the authenticated customer. Secrets are never returned, only metadata. - */ - service_token_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_list'; - arguments: components['schemas']['ListServiceTokensInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['ListServiceTokensOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get service token - * @description Get detailed information about a specific service token. The secret is never returned. - */ - service_token_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_get", - * "arguments": { - * "id": "1234567890" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_get'; - arguments: components['schemas']['GetServiceTokenInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['GetServiceTokenOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update service token - * @description Update a service token. Only name, description, and expiration can be modified. - */ - service_token_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_update */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_update", - * "arguments": { - * "id": "1234567890" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_update'; - arguments: components['schemas']['UpdateServiceTokenInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['UpdateServiceTokenOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Archive service token - * @description Archive (soft delete) a service token. This immediately invalidates the token for authentication. - */ - service_token_archive: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_archive */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_archive", - * "arguments": { - * "id": "1234567890" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_archive'; - arguments: components['schemas']['ArchiveServiceTokenInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['ArchiveServiceTokenOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get customer info - * @description Get detailed information about a customer from the core database. - */ - customer_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for customer_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "customer_get", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'customer_get'; - arguments: components['schemas']['GetCustomerInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['GetCustomerOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get customer seats - * @description Get all seats associated with a customer from the core database. - */ - customer_get_seats: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for customer_get_seats */ - requestBody: { - content: { - /** - * @example { - * "tool": "customer_get_seats", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'customer_get_seats'; - arguments: components['schemas']['GetCustomerSeatsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['GetCustomerSeatsOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; -} diff --git a/src/types/platform-api.ts b/src/types/platform-api.ts deleted file mode 100644 index 2449ff6..0000000 --- a/src/types/platform-api.ts +++ /dev/null @@ -1,5420 +0,0 @@ -/** - * This file was auto-generated by openapi-typescript. - * Do not make direct changes to the file. - */ - -export interface paths { - '/mcp-initialize': { - /** - * Initialize MCP session - * @description Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as a UUID and included in the mcp-session-id header for all subsequent requests. - */ - post: operations['mcp_initialize']; - }; - '/brand-agent-list': { - /** - * List brand agents - * @description List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. - */ - post: operations['brand_agent_list']; - }; - '/brand-agent-get': { - /** - * Get brand agent - * @description Get detailed information about a specific brand agent (advertiser account) by ID. - */ - post: operations['brand_agent_get']; - }; - '/brand-agent-create': { - /** - * Create brand agent - * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. - */ - post: operations['brand_agent_create']; - }; - '/brand-agent-update': { - /** - * Update brand agent - * @description Update an existing brand agent with new information. - */ - post: operations['brand_agent_update']; - }; - '/brand-agent-delete': { - /** - * Delete brand agent - * @description Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. - */ - post: operations['brand_agent_delete']; - }; - '/campaign-list': { - /** - * List campaigns - * @description List all campaigns with optional filtering by brand agent. - */ - post: operations['campaign_list']; - }; - '/campaign-create': { - /** - * Create campaign - * @description Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. - */ - post: operations['campaign_create']; - }; - '/campaign-get': { - /** - * Get campaign - * @description Get detailed information about a specific campaign. - */ - post: operations['campaign_get']; - }; - '/campaign-update': { - /** - * Update campaign - * @description Update an existing campaign with new information. - */ - post: operations['campaign_update']; - }; - '/campaign-delete': { - /** - * Delete campaign - * @description Delete a campaign and all associated resources. - */ - post: operations['campaign_delete']; - }; - '/campaign-get-summary': { - /** - * Get campaign summary - * @description Get a high-level summary of a campaign including key metrics and status. - */ - post: operations['campaign_get_summary']; - }; - '/campaign-list-tactics': { - /** - * List campaign tactics - * @description List all tactics associated with a specific campaign. - */ - post: operations['campaign_list_tactics']; - }; - '/campaign-validate-brief': { - /** - * Validate campaign brief - * @description Validate a campaign brief to ensure it contains all necessary information for campaign creation. - */ - post: operations['campaign_validate_brief']; - }; - '/asset-list': { - /** - * List assets - * @description List all uploaded assets with optional filtering by brand agent. - */ - post: operations['asset_list']; - }; - '/brand-standards-create': { - /** - * Create brand standards - * @description Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand agent. - */ - post: operations['brand_standards_create']; - }; - '/brand-standards-delete': { - /** - * Delete brand standards - * @description Delete brand standards for a brand agent. - */ - post: operations['brand_standards_delete']; - }; - '/brand-standards-list': { - /** - * List brand standards - * @description List all brand standards with optional filtering by brand agent. - */ - post: operations['brand_standards_list']; - }; - '/brand-story-create': { - /** - * Create brand story - * @description Create a brand story containing the narrative, history, values, and key messaging for a brand agent. - */ - post: operations['brand_story_create']; - }; - '/brand-story-update': { - /** - * Update brand story - * @description Update an existing brand story with new information. - */ - post: operations['brand_story_update']; - }; - '/brand-story-delete': { - /** - * Delete brand story - * @description Delete a brand story. - */ - post: operations['brand_story_delete']; - }; - '/brand-story-list': { - /** - * List brand stories - * @description List all brand stories with optional filtering by brand agent. - */ - post: operations['brand_story_list']; - }; - '/channel-list': { - /** - * List channels - * @description List all available advertising channels and platforms. - */ - post: operations['channel_list']; - }; - '/country-list': { - /** - * List countries - * @description Get all available countries for targeting. Use this to get valid country codes before creating brand agents. - */ - post: operations['country_list']; - }; - '/language-list': { - /** - * List languages - * @description Get all available languages for targeting. Use this to get valid language codes before creating brand stories. - */ - post: operations['language_list']; - }; - '/creative-assign': { - /** - * Assign creative - * @description Assign a creative to a tactic or media buy. - */ - post: operations['creative_assign']; - }; - '/creative-create': { - /** - * Create creative - * @description Create a new creative with assets, copy, and targeting specifications. - */ - post: operations['creative_create']; - }; - '/creative-update': { - /** - * Update creative - * @description Update an existing creative with new assets, copy, or specifications. - */ - post: operations['creative_update']; - }; - '/creative-delete': { - /** - * Delete creative - * @description Delete a creative and remove it from any associated tactics or media buys. - */ - post: operations['creative_delete']; - }; - '/creative-get': { - /** - * Get creative - * @description Get detailed information about a specific creative. - */ - post: operations['creative_get']; - }; - '/creative-list': { - /** - * List creatives - * @description List all creatives with optional filtering by brand agent or campaign. - */ - post: operations['creative_list']; - }; - '/media-buy-get': { - /** - * Get media buy - * @description Get detailed information about a specific media buy. - */ - post: operations['media_buy_get']; - }; - '/media-buy-list': { - /** - * List media buys - * @description List all media buys with optional filtering by brand agent, campaign, or status. - */ - post: operations['media_buy_list']; - }; - '/media-product-list': { - /** - * List media products - * @description List saved media products with optional filtering. - */ - post: operations['media_product_list']; - }; - '/agent-get': { - /** - * Get agent - * @description Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the agent ID. - */ - post: operations['agent_get']; - }; - '/agent-list': { - /** - * List agents - * @description List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - */ - post: operations['agent_list']; - }; - '/tactic-get': { - /** - * Get tactic - * @description Get detailed information about a specific tactic. - */ - post: operations['tactic_get']; - }; - '/tactic-list': { - /** - * List tactics - * @description List all tactics with optional filtering by brand agent or campaign. - */ - post: operations['tactic_list']; - }; - '/outcomes-agent-get-proposals': { - /** - * Get proposals from outcome agents - * @description Request tactical proposals from outcome agents for a campaign. Outcome agents analyze the campaign brief and budget to propose execution strategies. - */ - post: operations['outcomes_agent_get_proposals']; - }; - '/outcomes-agent-accept-proposal': { - /** - * Accept outcome agent proposal - * @description Accept a proposal from an outcome agent, creating a tactic and assigning it to the agent for management. - */ - post: operations['outcomes_agent_accept_proposal']; - }; - '/outcomes-agent-list-tactics': { - /** - * List tactics by outcome agent - * @description List all tactics managed by a specific outcome agent. - */ - post: operations['outcomes_agent_list_tactics']; - }; - '/service-token-create': { - /** - * Create service token - * @description Create a new service token for API authentication. Returns the full token which should be stored securely as it cannot be retrieved later. - */ - post: operations['service_token_create']; - }; - '/service-token-list': { - /** - * List service tokens - * @description List all service tokens for the authenticated customer. Secrets are never returned, only metadata. - */ - post: operations['service_token_list']; - }; - '/service-token-get': { - /** - * Get service token - * @description Get detailed information about a specific service token. The secret is never returned. - */ - post: operations['service_token_get']; - }; - '/service-token-update': { - /** - * Update service token - * @description Update a service token. Only name, description, and expiration can be modified. - */ - post: operations['service_token_update']; - }; - '/service-token-archive': { - /** - * Archive service token - * @description Archive (soft delete) a service token. This immediately invalidates the token for authentication. - */ - post: operations['service_token_archive']; - }; - '/customer-get': { - /** - * Get customer info - * @description Get detailed information about a customer from the core database. - */ - post: operations['customer_get']; - }; - '/customer-get-seats': { - /** - * Get customer seats - * @description Get all seats associated with a customer from the core database. - */ - post: operations['customer_get_seats']; - }; -} - -export type webhooks = Record; - -export interface components { - schemas: { - /** @description Budget range for campaign planning */ - BudgetRange: { - /** - * @description Minimum budget available - * @example 50000 - */ - min: number; - /** - * @description Maximum budget available - * @example 150000 - */ - max: number; - /** - * @description Currency for budget (ISO 4217 code) - * @default USD - * @example USD - */ - currency?: string; - }; - /** @description Visual card data for rendering proposals in marketplace UI, following ADCP product card pattern */ - ProposalCard: { - /** - * @description Proposal name/title - * @example Premium Display Campaign - */ - title: string; - /** - * @description What the proposal offers - * @example Target premium inventory at $2.50 vCPM with 85% viewability guarantee - */ - description: string; - /** - * @description Optional array of image URLs showcasing the approach - * @example [ - * "https://example.com/chart1.png", - * "https://example.com/viz2.png" - * ] - */ - image_carousel?: string[]; - /** - * @description Markdown-formatted detailed execution plan and specifications - * @example ## Execution Strategy - * - * We will target... - */ - details?: string; - /** @description Pricing information for comparison */ - pricing_summary: { - /** - * @description Human-readable pricing method - * @example 15% revenue share - */ - method: string; - /** - * @description Human-readable budget capacity - * @example $50,000 maximum - */ - budget_capacity: string; - /** - * @description Optional estimated cost calculation - * @example $7,500 estimated fee - */ - estimated_cost?: string; - }; - }; - ListAssetsInput: { - /** - * @description Optional brand agent ID to filter assets - * @example 100 - */ - brandAgentId?: number; - }; - /** @description Parameters for listing brand agents. Authentication is automatic. */ - ListBrandAgentsInput: { - /** @description Prisma-style where clause for filtering agents */ - where?: { - [key: string]: unknown; - }; - /** @description Prisma-style orderBy clause */ - orderBy?: { - [key: string]: unknown; - }; - /** - * @description Number of records to return - * @example 10 - */ - take?: number; - /** - * @description Number of records to skip - * @example 0 - */ - skip?: number; - /** - * @description Fields to use for distinct selection - * @example [] - */ - distinct?: string[]; - }; - /** @description Parameters for retrieving a specific brand agent */ - GetBrandAgentInput: { - /** - * @description The unique identifier for the brand agent - * @example 123 - */ - brandAgentId: number; - }; - /** @description Parameters for creating a new brand agent */ - CreateBrandAgentInput: { - /** - * @description Name of the brand agent (advertiser account) - * @example Nike Global Campaigns - */ - name: string; - /** - * @description Optional description of the brand agent - * @example Brand agent for Nike global advertising campaigns - */ - description?: string; - /** - * Format: uri - * @description URL to the brand manifest - * @example https://example.com/brand-manifest - */ - manifestUrl?: string; - /** - * @description Country codes (ISO 3166-1 alpha-2) - * @example [ - * "US", - * "CA", - * "GB" - * ] - */ - countryCodes?: string[]; - }; - /** @description Parameters for updating a brand agent */ - UpdateBrandAgentInput: { - /** - * @description The unique identifier for the brand agent - * @example 123 - */ - brandAgentId: number; - /** - * @description Updated name of the brand agent - * @example Example Name - */ - name?: string; - /** - * @description Updated description - * @example string - */ - description?: string; - /** - * Format: uri - * @description Updated URL to the brand manifest - * @example https://example.com/brand-manifest - */ - manifestUrl?: string; - /** - * @description Updated country codes - * @example [] - */ - countryCodes?: string[]; - }; - /** @description Parameters for deleting a brand agent */ - DeleteBrandAgentInput: { - /** - * @description The unique identifier for the brand agent to delete - * @example 123 - */ - brandAgentId: number; - }; - CreateBrandStandardInput: { - /** - * @description Brand agent ID - * @example 100 - */ - brandAgentId: number; - /** - * @description Standard name - * @example Example Name - */ - name?: string; - /** - * @description Standard description - * @example string - */ - description?: string; - /** - * @description Brand standards prompt - * @example string - */ - prompt: string; - /** - * @description Whether this is the primary standard - * @example true - */ - isPrimary?: boolean; - /** - * @description Country codes - * @example [] - */ - countries?: string[]; - /** - * @description Channel types - * @example [] - */ - channels?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; - /** - * @description Brand names - * @example [] - */ - brands?: string[]; - }; - DeleteBrandStandardInput: { - /** - * @description Brand standard ID - * @example example_id_123 - */ - brandStandardId: string; - }; - ListBrandStandardsInput: { - /** - * @description Optional brand agent ID to filter brand standards by - * @example 100 - */ - brandAgentId?: number; - /** @description Prisma-style where clause for filtering standards */ - where?: { - [key: string]: unknown; - }; - /** @description Prisma-style orderBy clause */ - orderBy?: { - [key: string]: unknown; - }; - /** - * @description Number of records to return - * @example 100 - */ - take?: number; - /** - * @description Number of records to skip - * @example 100 - */ - skip?: number; - /** - * @description Fields to use for distinct selection - * @example [] - */ - distinct?: string[]; - }; - CreateBrandStoryInput: { - /** @description Brand agent ID (bigint or string) */ - brandAgentId: number | string; - /** - * @description Story name - * @example Example Name - */ - name: string; - /** - * @description Brand story prompt - * @example string - */ - prompt?: string; - /** - * @description Brand names - * @example [] - */ - brands?: string[]; - /** - * @description Language codes (use language_list tool to see available options) - * @example [] - */ - languages: string[]; - }; - UpdateBrandStoryInput: { - /** - * @description Brand story ID - * @example example_id_123 - */ - brandStoryId: string; - /** - * @description Story name - * @example Example Name - */ - name?: string; - /** - * @description Updated brand story prompt - * @example string - */ - prompt: string; - }; - DeleteBrandStoryInput: { - /** - * @description Brand story ID - * @example example_id_123 - */ - brandStoryId: string; - }; - ListBrandStoriesInput: { - /** - * @description Optional brand agent ID to filter brand stories by - * @example 100 - */ - brandAgentId?: number; - /** @description Filtering criteria */ - where?: { - [key: string]: unknown; - }; - /** @description Ordering criteria */ - orderBy?: { - [key: string]: unknown; - }; - /** - * @description Number of records to return - * @example 100 - */ - take?: number; - /** - * @description Number of records to skip - * @example 100 - */ - skip?: number; - /** - * @description Fields to use for distinct selection - * @example [] - */ - distinct?: string[]; - }; - /** @description Parameters for listing campaigns */ - ListCampaignsInput: { - /** - * @description Filter by brand agent ID - * @example 123 - */ - brandAgentId?: number; - /** - * @description Filter by campaign status - * @example ACTIVE - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; - /** - * @description Number of results to return - * @example 50 - */ - limit?: number; - /** - * @description Number of results to skip for pagination - * @example 0 - */ - offset?: number; - }; - /** @description Parameters for creating a new campaign */ - CreateCampaignInput: { - /** - * @description Brand agent ID that will own this campaign - * @example 123 - */ - brandAgentId: number; - /** - * @description Optional name for the campaign (auto-generated if not provided) - * @example Summer 2025 Tech Campaign - */ - name?: string; - /** - * @description Natural language description of campaign requirements. The backend will parse this to extract targeting, budget, and creative requirements. - * @example Create a video campaign targeting tech enthusiasts aged 25-45 with $50k budget - */ - prompt: string; - /** @description Budget configuration for the campaign */ - budget?: { - total: number; - /** @default USD */ - currency?: string; - dailyCap?: number; - /** @enum {string} */ - pacing?: 'EVEN' | 'ASAP' | 'FRONTLOADED'; - }; - /** - * Format: date-time - * @description Campaign start date (ISO 8601 format) - * @example 2025-01-15T00:00:00Z - */ - startDate?: string; - /** - * Format: date-time - * @description Campaign end date (ISO 8601 format) - * @example 2025-03-31T23:59:59Z - */ - endDate?: string; - /** @description Scoring weights for campaign optimization */ - scoringWeights?: { - affinity?: number; - outcome?: number; - quality?: number; - }; - /** - * @description Number of days for outcome measurement window - * @example 30 - */ - outcomeScoreWindowDays?: number; - /** - * @description Initial campaign status - * @example ACTIVE - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; - }; - /** @description Parameters for retrieving a specific campaign */ - GetCampaignInput: { - /** - * @description The unique identifier for the campaign - * @example cmp_987654321 - */ - campaignId: string; - }; - /** @description Parameters for updating a campaign */ - UpdateCampaignInput: { - /** - * @description The unique identifier for the campaign - * @example cmp_987654321 - */ - campaignId: string; - /** - * @description Updated campaign name - * @example Example Name - */ - name?: string; - /** - * @description Updated campaign prompt - * @example string - */ - prompt?: string; - /** @description Updated budget configuration */ - budget?: { - total?: number; - /** @default USD */ - currency?: string; - dailyCap?: number; - /** @enum {string} */ - pacing?: 'EVEN' | 'ASAP' | 'FRONTLOADED'; - }; - /** - * Format: date-time - * @description Updated start date - * @example string - */ - startDate?: string; - /** - * Format: date-time - * @description Updated end date - * @example string - */ - endDate?: string; - /** @description Updated scoring weights */ - scoringWeights?: { - affinity?: number; - outcome?: number; - quality?: number; - }; - /** - * @description Updated outcome score window days - * @example 100 - */ - outcomeScoreWindowDays?: number; - /** - * @description Updated campaign status - * @example ACTIVE - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; - }; - /** @description Parameters for deleting a campaign */ - DeleteCampaignInput: { - /** - * @description The unique identifier for the campaign to delete - * @example cmp_987654321 - */ - campaignId: string; - /** - * @description If true, permanently delete the campaign. Default: false (soft delete/archive) - * @example true - */ - hardDelete?: boolean; - }; - GetCampaignSummaryInput: { - /** - * @description Campaign ID - * @example example_id_123 - */ - campaignId: string; - }; - ListCampaignTacticsInput: { - /** - * @description Campaign ID - * @example example_id_123 - */ - campaignId: string; - }; - ValidateBriefInput: { - /** - * @description Campaign brief text - * @example string - */ - brief: string; - }; - ListChannelsInput: Record; - GetCustomerInput: { - /** - * @description The unique identifier of the customer to retrieve. If not provided, uses the authenticated users customer ID. - * @example 100 - */ - customerId?: number; - }; - GetCustomerSeatsInput: { - /** - * @description The unique identifier of the customer whose seats to retrieve. If not provided, uses the authenticated users customer ID. - * @example 100 - */ - customerId?: number; - }; - AssignCreativeInput: { - /** @example example_id_123 */ - creativeId: string; - /** @example example_id_123 */ - campaignId: string; - }; - CreateCreativeInput: { - /** @example 100 */ - brandAgentId: number; - /** @example example_id_123 */ - organizationId?: string; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** - * @example ADCP - * @enum {string} - */ - formatSource?: 'ADCP' | 'CREATIVE_AGENT' | 'PUBLISHER'; - /** - * @description Format identifier. For ADCP sources, this should be a format ID string recognized by the target sales agent (e.g., display_300x250, video_1920x1080). Valid formats are agent-specific. - * @example example_id_123 - */ - formatId?: string; - /** @example https://example.com */ - mediaUrl?: string; - /** - * @description Optional: Upload assets inline with the creative. Each asset requires: name, contentType, data (base64), and assetType. - * @example [] - */ - assets?: { - /** @description Filename (e.g., banner.png) */ - name: string; - /** @description MIME type (e.g., image/png, image/jpeg) */ - contentType: string; - /** - * Format: byte - * @description Base64-encoded file data (without data:image/png;base64, prefix) - */ - data: string; - /** - * @description Type of asset - * @enum {string} - */ - assetType: 'image' | 'video' | 'audio' | 'logo' | 'font'; - /** @description Optional tags */ - tags?: string[]; - }[]; - content?: { - [key: string]: unknown; - }; - /** - * @example CREATIVE_AGENT - * @enum {string} - */ - assemblyMethod?: 'CREATIVE_AGENT' | 'ACTIVATION' | 'PUBLISHER'; - /** - * @description Optional campaign ID (object ID) to assign creative to - * @example example_id_123 - */ - campaignId?: string; - }; - UpdateCreativeInput: { - /** @example example_id_123 */ - creativeId: string; - /** @example Example Name */ - name?: string; - /** @example string */ - status?: string; - }; - DeleteCreativeInput: { - /** @example example_id_123 */ - creativeId: string; - }; - GetCreativeInput: { - /** @example example_id_123 */ - creativeId: string; - }; - ListCreativesInput: { - /** @example 100 */ - campaignId?: number; - /** @example 100 */ - brandAgentId?: number; - /** - * @example ADCP - * @enum {string} - */ - formatSource?: 'ADCP' | 'CREATIVE_AGENT' | 'PUBLISHER'; - /** - * @example ACTIVE - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; - /** @example 100 */ - take?: number; - /** @example 100 */ - skip?: number; - }; - ListCountriesInput: Record; - ListLanguagesInput: Record; - GetMediaBuyInput: { - /** @example example_id_123 */ - mediaBuyId: string; - }; - ListMediaBuysInput: { - /** @example 100 */ - tacticId?: number; - /** - * @example DRAFT - * @enum {string} - */ - status?: - | 'DRAFT' - | 'PENDING_APPROVAL' - | 'ACTIVE' - | 'PAUSED' - | 'COMPLETED' - | 'FAILED' - | 'REJECTED'; - /** @example 100 */ - take?: number; - /** @example 100 */ - skip?: number; - }; - OutcomesAgentGetProposalsInput: { - /** - * @description Campaign ID to get proposals for - * @example camp_123 - */ - campaignId: string; - /** - * @description Optional: Specific outcome agent IDs to query. If omitted, queries all outcome agents. - * @example [ - * "agent_123", - * "agent_456" - * ] - */ - agentIds?: string[]; - budgetRange?: components['schemas']['BudgetRange']; - /** - * Format: date-time - * @description Campaign start date (ISO 8601) - * @example 2025-01-01T00:00:00Z - */ - startDate?: string; - /** - * Format: date-time - * @description Campaign end date (ISO 8601) - * @example 2025-01-31T23:59:59Z - */ - endDate?: string; - /** - * @description Advertising channels - * @example [ - * "display", - * "video" - * ] - */ - channels?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; - /** - * @description ISO 3166-1 alpha-2 country codes - * @example [ - * "US", - * "CA" - * ] - */ - countries?: string[]; - /** - * @description Campaign brief text - * @example string - */ - brief?: string; - }; - OutcomesAgentAcceptProposalInput: { - /** - * @description Database ID of the proposal to accept - * @example 123 - */ - proposalId: string; - /** - * @description Optional: Name for the tactic/strategy that will be created. If not provided, a unique identifier will be generated. - * @example Premium Display Campaign - */ - tacticName?: string; - /** @description Optional custom fields required by the outcome agent */ - customFields?: { - [key: string]: unknown; - }; - }; - OutcomesAgentListTacticsInput: { - /** - * @description ID of the outcome agent to list tactics for - * @example 123 - */ - outcomeAgentId: string; - }; - ListProductsInput: { - /** @example 100 */ - take?: number; - /** @example 100 */ - skip?: number; - }; - GetAgentInput: { - /** - * @description The agent ID to retrieve - * @example example_id_123 - */ - agentId: string; - }; - ListAgentsInput: { - /** - * @description Filter by agent type (SALES or OUTCOME) - * @example SALES - * @enum {string} - */ - type?: 'SALES' | 'OUTCOME'; - /** - * @description Filter by status (PENDING, ACTIVE, DISABLED) - * @example PENDING - * @enum {string} - */ - status?: 'PENDING' | 'ACTIVE' | 'DISABLED'; - /** - * @description Filter by organization ID - * @example example_id_123 - */ - organizationId?: string; - /** - * @description Filter by relationship (SELF = owned by you, SCOPE3 = Scope3-provided, MARKETPLACE = third-party marketplace agents) - * @example SELF - * @enum {string} - */ - relationship?: 'SELF' | 'SCOPE3' | 'MARKETPLACE'; - /** - * @description Filter by agent name (partial match) - * @example Example Name - */ - name?: string; - }; - GetTacticInput: { - /** @example 100 */ - tacticId: number; - }; - ListTacticsInput: { - /** @example example_id_123 */ - campaignId?: string; - /** @example 100 */ - take?: number; - /** @example 100 */ - skip?: number; - }; - CreateServiceTokenInput: { - /** - * @description Human-readable name for the service token - * @example Example Name - */ - name: string; - /** - * @description Optional description of the token purpose and usage - * @example string - */ - description?: string; - /** - * @description Number of days until token expiration (max 365). If not provided, token does not expire - * @example 100 - */ - expiresInDays?: number; - /** - * @description Token scope: CUSTOMER (full customer access) or SEAT (scoped to specific seat) - * @default CUSTOMER - * @enum {string} - */ - scope?: 'CUSTOMER' | 'SEAT'; - /** - * @description Seat name (required when scope is SEAT). The seat will be looked up for the customer. - * @example Example Name - */ - seatName?: string; - }; - UpdateServiceTokenInput: { - /** - * Format: int64 - * @description The unique identifier of the service token to update - * @example 100 - */ - id: number; - /** - * @description Updated human-readable name for the service token - * @example Example Name - */ - name?: string; - /** - * @description Updated description of the token purpose and usage - * @example string - */ - description?: string; - /** - * @description Number of days to extend expiration from now (max 365). Updates the expiresAt timestamp - * @example 100 - */ - expiresInDays?: number; - }; - ArchiveServiceTokenInput: { - /** - * Format: int64 - * @description The unique identifier of the service token to archive - * @example 100 - */ - id: number; - }; - GetServiceTokenInput: { - /** - * Format: int64 - * @description The unique identifier of the service token to retrieve - * @example 100 - */ - id: number; - /** - * @description Whether to fetch the access_client_secret from Google Secret Manager. Defaults to false for security - * @default false - */ - includeSecret?: boolean; - }; - ListServiceTokensInput: { - /** - * @description Whether to include archived tokens in the response - * @default false - */ - includeArchived?: boolean; - /** - * Format: int64 - * @description Filter tokens by seat ID - * @example 100 - */ - seatId?: number; - /** - * Format: int64 - * @description Filter tokens by user ID - * @example 100 - */ - userId?: number; - }; - BrandAgentUpdate: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** - * Format: uri - * @example https://example.com - */ - manifestUrl?: string; - /** @example 100 */ - customerId: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - BrandStandardsCreate: { - /** @example example_id_123 */ - id: string; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** @example [] */ - countryCodes: string[]; - /** @example [] */ - channelCodes: string[]; - /** @example [] */ - brands: string[]; - /** @example [] */ - models: { - id: string; - name: string; - prompt: string; - status: string | null; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }[]; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - CampaignUpdate: { - /** @example example_id_123 */ - campaignId: string; - /** @example Example Name */ - name: string; - /** @example string */ - status: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - CreativeGet: { - /** @example example_id_123 */ - creativeId: string; - /** @example Example Name */ - name: string; - /** @example string */ - status: string; - /** @example example_id_123 */ - campaignId?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - MediaBuyGet: { - /** @example example_id_123 */ - id: string; - /** @example 100 */ - tacticId: number; - /** @example 100 */ - customerId: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** @example [] */ - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - /** @example string */ - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - TacticGet: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - prompt?: string; - /** @example [] */ - campaignIds?: string[]; - /** @example [] */ - channelCodes: string[]; - /** @example [] */ - countryCodes: string[]; - /** @example 100 */ - mediaBuyCount?: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - }; - MCPContent: { - /** - * @example text - * @enum {string} - */ - type: 'text'; - /** @example string */ - text: string; - }; - /** @description Bad request error response */ - BadRequest: { - /** @example string */ - error: string; - /** @example string */ - message?: string; - }; - /** @description Unauthorized error response */ - Unauthorized: { - /** @example string */ - error: string; - /** @example string */ - message?: string; - }; - /** @description Internal server error response */ - InternalError: { - /** @example string */ - error: string; - /** @example string */ - message?: string; - }; - AssetList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - assetId: string; - originalFilename: string; - assetType: string; - size: number; - brandAgentId: string; - customerId: number; - signedUrl: string; - tags?: string[]; - }[]; - }; - BrandAgentList: { - /** @example [] */ - brandAgents: components['schemas']['BrandAgentUpdateOutput'][]; - /** @example 100 */ - total: number; - }; - BrandAgentDelete: { - /** @example true */ - success: boolean; - /** @example 100 */ - deletedId: number; - }; - BrandStandardsDelete: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - id: string; - }; - BrandStandardsList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: components['schemas']['BrandStandardsCreateOutput'][]; - }; - BrandStoryCreate: { - /** @example example_id_123 */ - id: string; - /** @example Example Name */ - name: string; - /** @example example_id_123 */ - brandAgentId?: string; - /** @example [] */ - countryCodes?: string[]; - /** @example [] */ - channelCodes?: string[]; - /** @example [] */ - languages?: string[]; - /** @example [] */ - brands?: string[]; - currentModel?: { - id: string; - name: string; - prompt: string; - status: string | null; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - BrandStoryUpdate: { - /** @example example_id_123 */ - id: string; - /** @example Example Name */ - name: string; - /** @example string */ - prompt?: string; - /** @example string */ - status?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - BrandStoryDelete: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - id: string; - }; - BrandStoryList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - id: string; - name: string; - description?: string; - status: string; - type: string; - languages: string[]; - currentModel?: { - id: string; - name: string; - prompt: string; - status: string | null; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }[]; - }; - CampaignList: { - /** @example [] */ - campaigns: components['schemas']['CampaignUpdateOutput'][]; - /** @example 100 */ - total: number; - }; - CampaignDelete: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - deletedId: string; - }; - CampaignGetSummary: { - /** @example example_id_123 */ - campaignId: string; - summary: { - [key: string]: unknown; - }; - }; - CampaignListTactics: { - /** @example [] */ - tactics: unknown[]; - /** @example 100 */ - total: number; - }; - CampaignValidateBrief: { - /** @example true */ - valid: boolean; - /** @example string */ - feedback?: string; - }; - ChannelList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - channel: string; - displayName: string; - }[]; - }; - GetCustomerOutput: { - /** - * @description Unique identifier for the customer - * @example 100 - */ - id: number; - /** - * @description Company name - * @example string - */ - company: string; - /** - * @description Customer display name - * @example Example Name - */ - name: string; - /** - * @description Whether the customer is currently active - * @example true - */ - active: boolean; - /** - * Format: date-time - * @description ISO 8601 timestamp when the customer was created - * @example string - */ - createdAt: string; - }; - GetCustomerSeatsOutput: { - /** - * @description The customer ID these seats belong to - * @example 100 - */ - customerId: number; - /** - * @description Array of seats belonging to the customer - * @example [] - */ - seats: { - /** @description Unique identifier for the seat */ - id: string; - /** @description Seat display name */ - name: string; - /** @description Customer ID that owns this seat */ - customerId: number; - /** @description Whether the seat is currently active */ - active: boolean; - }[]; - /** - * @description Total number of seats returned - * @example 100 - */ - count: number; - }; - CreativeAssign: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - creativeId: string; - /** @example example_id_123 */ - campaignId: string; - }; - CreativeDelete: { - /** @example true */ - success: boolean; - /** @example example_id_123 */ - id: string; - }; - CreativeList: { - /** @example [] */ - items: components['schemas']['CreativeGetOutput'][]; - /** @example 100 */ - total: number; - }; - CountryList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - key: string; - displayName: string; - }[]; - }; - LanguageList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - key: string; - displayName: string; - }[]; - }; - MediaBuyList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: components['schemas']['MediaBuyGetOutput'][]; - }; - OutcomesAgentGetProposals: { - /** - * @description Total number of proposals returned - * @example 100 - */ - total: number; - /** - * @description List of proposals from outcome agents - * @example [] - */ - proposals: { - /** @description Database ID of the proposal */ - id: string; - /** @description Outcome agent generated proposal ID */ - proposalId: string; - /** @description ID of the outcome agent that created this proposal */ - outcomeAgentId: string; - /** @description Name of the outcome agent */ - outcomeAgentName: string; - /** @description How the proposal would be executed */ - execution: string; - /** @description Maximum budget the agent can manage */ - budgetCapacity: number; - /** @description Pricing model for the proposal */ - pricing: { - /** @enum {string} */ - method: 'revshare' | 'cost_per_unit'; - rate: number; - /** @enum {string} */ - pricing_model?: 'cpm' | 'cpc' | 'cpa' | 'cpv' | 'cpcv'; - currency: string; - }; - /** @description Tactic type identifier */ - sku?: string; - /** - * @description Current status of the proposal - * @enum {string} - */ - status: 'pending' | 'accepted' | 'rejected' | 'expired'; - /** @description Visual card data for rendering in UI */ - proposalCard?: components['schemas']['ProposalCardOutput']; - /** - * Format: date-time - * @description When the proposal was created - */ - createdAt: string; - }[]; - }; - OutcomesAgentAcceptProposal: { - /** - * @description ID of the created tactic/strategy - * @example example_id_123 - */ - tacticId: string; - /** - * @description Name of the created tactic (user-provided or auto-generated) - * @example Example Name - */ - tacticName: string; - /** - * @description ID of the accepted proposal - * @example example_id_123 - */ - proposalId: string; - /** - * @description ID of the outcome agent managing this tactic - * @example example_id_123 - */ - outcomeAgentId: string; - /** - * @description Whether the outcome agent acknowledged the assignment - * @example true - */ - acknowledged: boolean; - /** - * @description Optional message from the outcome agent - * @example string - */ - message?: string; - }; - OutcomesAgentListTactics: { - /** - * @description ID of the outcome agent - * @example example_id_123 - */ - outcomeAgentId: string; - /** - * @description Name of the outcome agent - * @example Example Name - */ - outcomeAgentName: string; - /** - * @description Total number of tactics managed by this agent - * @example 100 - */ - total: number; - /** - * @description List of tactics managed by this outcome agent - * @example [] - */ - tactics: { - /** @description ID of the tactic (strategy) */ - tacticId: string; - /** @description Name of the tactic */ - tacticName: string; - /** @description ID of the original proposal */ - proposalId: string; - /** @description When the proposal was accepted (ISO 8601) */ - acceptedAt: string; - /** @description Campaign ID if linked to a campaign */ - campaignId: string | null; - }[]; - }; - MediaProductList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: { - id: string; - productId: string; - name: string; - salesAgent?: string; - salesAgentId?: string; - salesAgentName?: string; - /** @enum {string} */ - deliveryType: 'guaranteed' | 'non_guaranteed'; - format?: string; - creativeFormats?: - | string[] - | { - agent_url: string; - id: string; - }[]; - }[]; - }; - AgentGet: - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - authenticationType: string; - description?: string; - organizationId?: string; - registeredBy?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - } - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - authenticationType: string; - description?: string; - organizationId?: string; - registeredBy?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - customerAccountCount: number; - }; - AgentList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: ( - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - } - | { - agentId: string; - name: string; - /** @enum {string} */ - type: 'SALES' | 'OUTCOME'; - status: string; - relationship: string; - endpointUrl: string; - protocol: string; - customerAccountCount: number; - } - )[]; - }; - TacticList: { - /** @example 100 */ - total: number; - /** @example [] */ - items: components['schemas']['TacticGetOutput'][]; - }; - CreateServiceTokenOutput: { - /** - * Format: int64 - * @description Unique identifier for the service token - * @example 100 - */ - id: number; - /** - * @description Customer ID that owns this token - * @example 100 - */ - customerId: number; - /** - * Format: int64 - * @description Seat ID if token is scoped to a specific seat - * @example 100 - */ - seatId?: number; - /** - * Format: int64 - * @description User ID if token is scoped to a specific user - * @example 100 - */ - userId?: number; - /** - * @description Optional organization identifier for scoping the token - * @example example_id_123 - */ - organizationId?: string; - /** - * @description Human-readable name of the token - * @example Example Name - */ - name: string; - /** - * @description Description of the token purpose - * @example string - */ - description?: string; - /** - * @description The public client ID portion of the token credentials (safe to log) - * @example example_id_123 - */ - accessClientId: string; - /** - * @description The secret portion of the token credentials. ONLY returned on creation, never retrievable again! - * @example string - */ - accessClientSecret: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token expires, if set - * @example string - */ - expiresAt?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was created - * @example string - */ - createdAt: string; - }; - UpdateServiceTokenOutput: { - /** - * Format: int64 - * @description Unique identifier for the service token - * @example 100 - */ - id: number; - /** - * @description Updated human-readable name of the token - * @example Example Name - */ - name: string; - /** - * @description Updated description of the token purpose - * @example string - */ - description?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token expires, if updated - * @example string - */ - expiresAt?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was last updated - * @example string - */ - updatedAt: string; - }; - ArchiveServiceTokenOutput: { - /** - * Format: int64 - * @description Unique identifier for the archived token - * @example 100 - */ - id: number; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was archived - * @example string - */ - archivedAt: string; - }; - GetServiceTokenOutput: { - /** - * Format: int64 - * @description Unique identifier for the service token - * @example 100 - */ - id: number; - /** - * @description Customer ID that owns this token - * @example 100 - */ - customerId: number; - /** - * Format: int64 - * @description Seat ID if token is scoped to a specific seat - * @example 100 - */ - seatId?: number; - /** - * Format: int64 - * @description User ID if token is scoped to a specific user - * @example 100 - */ - userId?: number; - /** - * @description Optional organization identifier for scoping the token - * @example example_id_123 - */ - organizationId?: string; - /** - * @description Human-readable name of the token - * @example Example Name - */ - name: string; - /** - * @description Description of the token purpose - * @example string - */ - description?: string; - /** - * @description The public client ID portion of the token credentials (safe to log) - * @example example_id_123 - */ - accessClientId: string; - /** - * @description The secret portion of the token credentials. Only included if includeSecret=true was passed - * @example string - */ - accessClientSecret?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token expires, if set - * @example string - */ - expiresAt?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was created - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was last updated - * @example string - */ - updatedAt: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was archived, if archived - * @example string - */ - archivedAt?: string; - }; - ListServiceTokensOutput: { - /** - * @description Array of service tokens. Note: accessClientSecret is never included in list responses - * @example [] - */ - tokens: { - /** - * Format: int64 - * @description Unique identifier for the service token - */ - id: number; - /** @description Customer ID that owns this token */ - customerId: number; - /** - * Format: int64 - * @description Seat ID if token is scoped to a specific seat - */ - seatId?: number; - /** @description Seat name if token is scoped to a specific seat */ - seatName?: string; - /** - * Format: int64 - * @description User ID if token is scoped to a specific user - */ - userId?: number; - /** @description Optional organization identifier for scoping the token */ - organizationId?: string; - /** @description Human-readable name of the token */ - name: string; - /** @description Description of the token purpose */ - description?: string; - /** @description The public client ID portion of the token credentials (safe to log) */ - accessClientId: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token expires, if set - */ - expiresAt?: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was created - */ - createdAt: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was last updated - */ - updatedAt: string; - /** - * Format: date-time - * @description ISO 8601 timestamp when the token was archived, if archived - */ - archivedAt?: string; - }[]; - /** - * @description Total number of tokens returned - * @example 100 - */ - count: number; - }; - /** @description Visual card data for rendering proposals in marketplace UI, following ADCP product card pattern */ - ProposalCardOutput: { - /** - * @description Proposal name/title - * @example Premium Display Campaign - */ - title: string; - /** - * @description What the proposal offers - * @example Target premium inventory at $2.50 vCPM with 85% viewability guarantee - */ - description: string; - /** - * @description Optional array of image URLs showcasing the approach - * @example [ - * "https://example.com/chart1.png", - * "https://example.com/viz2.png" - * ] - */ - image_carousel?: string[]; - /** - * @description Markdown-formatted detailed execution plan and specifications - * @example ## Execution Strategy - * - * We will target... - */ - details?: string; - /** @description Pricing information for comparison */ - pricing_summary: { - /** - * @description Human-readable pricing method - * @example 15% revenue share - */ - method: string; - /** - * @description Human-readable budget capacity - * @example $50,000 maximum - */ - budget_capacity: string; - /** - * @description Optional estimated cost calculation - * @example $7,500 estimated fee - */ - estimated_cost?: string; - }; - }; - /** @description Budget range for campaign planning */ - BudgetRangeOutput: { - /** - * @description Minimum budget available - * @example 50000 - */ - min: number; - /** - * @description Maximum budget available - * @example 150000 - */ - max: number; - /** - * @description Currency for budget (ISO 4217 code) - * @default USD - * @example USD - */ - currency: string; - }; - BrandAgentUpdateOutput: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** - * Format: uri - * @example https://example.com - */ - manifestUrl?: string; - /** @example 100 */ - customerId: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - BrandStandardsCreateOutput: { - /** @example example_id_123 */ - id: string; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** @example [] */ - countryCodes: string[]; - /** @example [] */ - channelCodes: string[]; - /** @example [] */ - brands: string[]; - /** @example [] */ - models: { - id: string; - name: string; - prompt: string; - status: string | null; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }[]; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - CampaignUpdateOutput: { - /** @example example_id_123 */ - campaignId: string; - /** @example Example Name */ - name: string; - /** @example string */ - status: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - CreativeGetOutput: { - /** @example example_id_123 */ - creativeId: string; - /** @example Example Name */ - name: string; - /** @example string */ - status: string; - /** @example example_id_123 */ - campaignId?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - MediaBuyGetOutput: { - /** @example example_id_123 */ - id: string; - /** @example 100 */ - tacticId: number; - /** @example 100 */ - customerId: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** @example [] */ - products?: { - mediaProductId: string; - salesAgentId: string; - salesAgentName?: string; - budgetAmount?: number; - budgetCurrency?: string; - pricingCpm?: number; - pricingSignalCost?: number; - displayOrder?: number; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - packages?: { - packageId: string; - productIds: string[]; - impressions: number; - budget: number; - targetingOverlay: unknown; - creatives: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - salesAgentId?: string; - salesAgentName?: string; - pricingCpm?: number; - pricingSignalCost?: number; - bidPrice?: number; - pricingOptionId?: string; - creativeFormats?: { - agent_url: string; - id: string; - }[]; - }[]; - /** @example [] */ - creatives?: { - creativeId: string; - name: string; - formatId: string; - mediaUrl: string; - status: string; - }[]; - pricing: { - cpm: number; - signalCost?: number; - totalCpm: number; - }; - /** @example string */ - status: string; - adcp?: { - mediaBuyId?: string; - status?: string; - webhookUrl?: string; - }; - performance?: { - impressions: number; - spend: number; - clicks: number; - /** Format: date-time */ - lastUpdated?: string; - }; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - TacticGetOutput: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - prompt?: string; - /** @example [] */ - campaignIds?: string[]; - /** @example [] */ - channelCodes: string[]; - /** @example [] */ - countryCodes: string[]; - /** @example 100 */ - mediaBuyCount?: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - /** - * Format: date-time - * @example string - */ - archivedAt?: string; - }; - BrandAgentGet: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** - * Format: uri - * @example https://example.com - */ - manifestUrl?: string; - /** @example 100 */ - customerId: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - BrandAgentCreate: { - /** @example 100 */ - id: number; - /** @example Example Name */ - name: string; - /** @example string */ - description?: string; - /** - * Format: uri - * @example https://example.com - */ - manifestUrl?: string; - /** @example 100 */ - customerId: number; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - CampaignCreate: { - /** @example example_id_123 */ - campaignId: string; - /** @example Example Name */ - name: string; - /** @example string */ - status: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - CampaignGet: { - /** @example example_id_123 */ - campaignId: string; - /** @example Example Name */ - name: string; - /** @example string */ - status: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - CreativeCreate: { - /** @example example_id_123 */ - creativeId: string; - /** @example Example Name */ - name: string; - /** @example string */ - status: string; - /** @example example_id_123 */ - campaignId?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - CreativeUpdate: { - /** @example example_id_123 */ - creativeId: string; - /** @example Example Name */ - name: string; - /** @example string */ - status: string; - /** @example example_id_123 */ - campaignId?: string; - /** - * Format: date-time - * @example string - */ - createdAt: string; - /** - * Format: date-time - * @example string - */ - updatedAt: string; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; -} - -export type $defs = Record; - -export type external = Record; - -export interface operations { - /** - * Initialize MCP session - * @description Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as a UUID and included in the mcp-session-id header for all subsequent requests. - */ - mcp_initialize: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Generate a new UUID for session initialization. */ - 'mcp-session-id': string; - }; - }; - requestBody: { - content: { - 'application/json': { - /** @enum {string} */ - jsonrpc: '2.0'; - id: string | number; - /** @enum {string} */ - method: 'initialize'; - params: { - /** @example 2024-11-05 */ - protocolVersion: string; - capabilities: Record; - clientInfo: { - name: string; - version: string; - }; - }; - }; - }; - }; - responses: { - /** @description Session initialized successfully */ - 200: { - content: { - 'application/json': { - /** @enum {string} */ - jsonrpc?: '2.0'; - id?: string | number; - result?: { - protocolVersion?: string; - capabilities?: Record; - serverInfo?: { - name?: string; - version?: string; - }; - }; - }; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - }; - }; - /** - * List brand agents - * @description List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. - */ - brand_agent_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_agent_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_agent_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_list'; - arguments: components['schemas']['ListBrandAgentsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get brand agent - * @description Get detailed information about a specific brand agent (advertiser account) by ID. - */ - brand_agent_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_agent_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_agent_get", - * "arguments": { - * "brandAgentId": 100 - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_get'; - arguments: components['schemas']['GetBrandAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create brand agent - * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. - */ - brand_agent_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_agent_create */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_agent_create", - * "arguments": { - * "name": "Example Name" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_create'; - arguments: components['schemas']['CreateBrandAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update brand agent - * @description Update an existing brand agent with new information. - */ - brand_agent_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_agent_update */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_agent_update", - * "arguments": { - * "brandAgentId": 100 - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_update'; - arguments: components['schemas']['UpdateBrandAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete brand agent - * @description Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. - */ - brand_agent_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_agent_delete */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_agent_delete", - * "arguments": { - * "brandAgentId": 100 - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_agent_delete'; - arguments: components['schemas']['DeleteBrandAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandAgentDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List campaigns - * @description List all campaigns with optional filtering by brand agent. - */ - campaign_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for campaign_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "campaign_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'campaign_list'; - arguments: components['schemas']['ListCampaignsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create campaign - * @description Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. - */ - campaign_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for campaign_create */ - requestBody: { - content: { - /** - * @example { - * "tool": "campaign_create", - * "arguments": { - * "brandAgentId": 100, - * "prompt": "string" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'campaign_create'; - arguments: components['schemas']['CreateCampaignInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get campaign - * @description Get detailed information about a specific campaign. - */ - campaign_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for campaign_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "campaign_get", - * "arguments": { - * "campaignId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'campaign_get'; - arguments: components['schemas']['GetCampaignInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update campaign - * @description Update an existing campaign with new information. - */ - campaign_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for campaign_update */ - requestBody: { - content: { - /** - * @example { - * "tool": "campaign_update", - * "arguments": { - * "campaignId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'campaign_update'; - arguments: components['schemas']['UpdateCampaignInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignUpdateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete campaign - * @description Delete a campaign and all associated resources. - */ - campaign_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for campaign_delete */ - requestBody: { - content: { - /** - * @example { - * "tool": "campaign_delete", - * "arguments": { - * "campaignId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'campaign_delete'; - arguments: components['schemas']['DeleteCampaignInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get campaign summary - * @description Get a high-level summary of a campaign including key metrics and status. - */ - campaign_get_summary: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for campaign_get_summary */ - requestBody: { - content: { - /** - * @example { - * "tool": "campaign_get_summary", - * "arguments": { - * "campaignId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'campaign_get_summary'; - arguments: components['schemas']['GetCampaignSummaryInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignGetSummary']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List campaign tactics - * @description List all tactics associated with a specific campaign. - */ - campaign_list_tactics: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for campaign_list_tactics */ - requestBody: { - content: { - /** - * @example { - * "tool": "campaign_list_tactics", - * "arguments": { - * "campaignId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'campaign_list_tactics'; - arguments: components['schemas']['ListCampaignTacticsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignListTactics']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Validate campaign brief - * @description Validate a campaign brief to ensure it contains all necessary information for campaign creation. - */ - campaign_validate_brief: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for campaign_validate_brief */ - requestBody: { - content: { - /** - * @example { - * "tool": "campaign_validate_brief", - * "arguments": { - * "brief": "string" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'campaign_validate_brief'; - arguments: components['schemas']['ValidateBriefInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CampaignValidateBrief']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List assets - * @description List all uploaded assets with optional filtering by brand agent. - */ - asset_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for asset_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "asset_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'asset_list'; - arguments: components['schemas']['ListAssetsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AssetList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create brand standards - * @description Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand agent. - */ - brand_standards_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_standards_create */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_standards_create", - * "arguments": { - * "brandAgentId": 100, - * "prompt": "string" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_standards_create'; - arguments: components['schemas']['CreateBrandStandardInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStandardsCreateOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete brand standards - * @description Delete brand standards for a brand agent. - */ - brand_standards_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_standards_delete */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_standards_delete", - * "arguments": { - * "brandStandardId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_standards_delete'; - arguments: components['schemas']['DeleteBrandStandardInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStandardsDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List brand standards - * @description List all brand standards with optional filtering by brand agent. - */ - brand_standards_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_standards_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_standards_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_standards_list'; - arguments: components['schemas']['ListBrandStandardsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStandardsList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create brand story - * @description Create a brand story containing the narrative, history, values, and key messaging for a brand agent. - */ - brand_story_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_story_create */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_story_create", - * "arguments": { - * "brandAgentId": null, - * "name": "Example Name", - * "languages": [] - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_story_create'; - arguments: components['schemas']['CreateBrandStoryInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStoryCreate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update brand story - * @description Update an existing brand story with new information. - */ - brand_story_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_story_update */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_story_update", - * "arguments": { - * "brandStoryId": "example_id_123", - * "prompt": "string" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_story_update'; - arguments: components['schemas']['UpdateBrandStoryInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStoryUpdate']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete brand story - * @description Delete a brand story. - */ - brand_story_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_story_delete */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_story_delete", - * "arguments": { - * "brandStoryId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_story_delete'; - arguments: components['schemas']['DeleteBrandStoryInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStoryDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List brand stories - * @description List all brand stories with optional filtering by brand agent. - */ - brand_story_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for brand_story_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "brand_story_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'brand_story_list'; - arguments: components['schemas']['ListBrandStoriesInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['BrandStoryList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List channels - * @description List all available advertising channels and platforms. - */ - channel_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for channel_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "channel_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'channel_list'; - arguments: components['schemas']['ListChannelsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['ChannelList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List countries - * @description Get all available countries for targeting. Use this to get valid country codes before creating brand agents. - */ - country_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for country_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "country_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'country_list'; - arguments: components['schemas']['ListCountriesInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CountryList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List languages - * @description Get all available languages for targeting. Use this to get valid language codes before creating brand stories. - */ - language_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for language_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "language_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'language_list'; - arguments: components['schemas']['ListLanguagesInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['LanguageList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Assign creative - * @description Assign a creative to a tactic or media buy. - */ - creative_assign: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for creative_assign */ - requestBody: { - content: { - /** - * @example { - * "tool": "creative_assign", - * "arguments": { - * "creativeId": "example_id_123", - * "campaignId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'creative_assign'; - arguments: components['schemas']['AssignCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeAssign']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create creative - * @description Create a new creative with assets, copy, and targeting specifications. - */ - creative_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for creative_create */ - requestBody: { - content: { - /** - * @example { - * "tool": "creative_create", - * "arguments": { - * "brandAgentId": 100, - * "name": "Example Name" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'creative_create'; - arguments: components['schemas']['CreateCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update creative - * @description Update an existing creative with new assets, copy, or specifications. - */ - creative_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for creative_update */ - requestBody: { - content: { - /** - * @example { - * "tool": "creative_update", - * "arguments": { - * "creativeId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'creative_update'; - arguments: components['schemas']['UpdateCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Delete creative - * @description Delete a creative and remove it from any associated tactics or media buys. - */ - creative_delete: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for creative_delete */ - requestBody: { - content: { - /** - * @example { - * "tool": "creative_delete", - * "arguments": { - * "creativeId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'creative_delete'; - arguments: components['schemas']['DeleteCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeDelete']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get creative - * @description Get detailed information about a specific creative. - */ - creative_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for creative_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "creative_get", - * "arguments": { - * "creativeId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'creative_get'; - arguments: components['schemas']['GetCreativeInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List creatives - * @description List all creatives with optional filtering by brand agent or campaign. - */ - creative_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for creative_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "creative_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'creative_list'; - arguments: components['schemas']['ListCreativesInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreativeList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get media buy - * @description Get detailed information about a specific media buy. - */ - media_buy_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_buy_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_buy_get", - * "arguments": { - * "mediaBuyId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_get'; - arguments: components['schemas']['GetMediaBuyInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List media buys - * @description List all media buys with optional filtering by brand agent, campaign, or status. - */ - media_buy_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_buy_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_buy_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_buy_list'; - arguments: components['schemas']['ListMediaBuysInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaBuyList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List media products - * @description List saved media products with optional filtering. - */ - media_product_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for media_product_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "media_product_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'media_product_list'; - arguments: components['schemas']['ListProductsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['MediaProductList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get agent - * @description Get detailed information about a specific agent (SALES or OUTCOME type). Type is automatically inferred from the agent ID. - */ - agent_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for agent_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "agent_get", - * "arguments": { - * "agentId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'agent_get'; - arguments: components['schemas']['GetAgentInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentGet']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List agents - * @description List all registered agents with comprehensive filtering. Supports filtering by type (SALES/OUTCOME), status, organization, relationship (SELF/SCOPE3/MARKETPLACE), and name. - */ - agent_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for agent_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "agent_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'agent_list'; - arguments: components['schemas']['ListAgentsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['AgentList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get tactic - * @description Get detailed information about a specific tactic. - */ - tactic_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for tactic_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "tactic_get", - * "arguments": { - * "tacticId": 100 - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'tactic_get'; - arguments: components['schemas']['GetTacticInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticGetOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List tactics - * @description List all tactics with optional filtering by brand agent or campaign. - */ - tactic_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for tactic_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "tactic_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'tactic_list'; - arguments: components['schemas']['ListTacticsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['TacticList']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get proposals from outcome agents - * @description Request tactical proposals from outcome agents for a campaign. Outcome agents analyze the campaign brief and budget to propose execution strategies. - */ - outcomes_agent_get_proposals: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for outcomes_agent_get_proposals */ - requestBody: { - content: { - /** - * @example { - * "tool": "outcomes_agent_get_proposals", - * "arguments": { - * "campaignId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'outcomes_agent_get_proposals'; - arguments: components['schemas']['OutcomesAgentGetProposalsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['OutcomesAgentGetProposals']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Accept outcome agent proposal - * @description Accept a proposal from an outcome agent, creating a tactic and assigning it to the agent for management. - */ - outcomes_agent_accept_proposal: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for outcomes_agent_accept_proposal */ - requestBody: { - content: { - /** - * @example { - * "tool": "outcomes_agent_accept_proposal", - * "arguments": { - * "proposalId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'outcomes_agent_accept_proposal'; - arguments: components['schemas']['OutcomesAgentAcceptProposalInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['OutcomesAgentAcceptProposal']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List tactics by outcome agent - * @description List all tactics managed by a specific outcome agent. - */ - outcomes_agent_list_tactics: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for outcomes_agent_list_tactics */ - requestBody: { - content: { - /** - * @example { - * "tool": "outcomes_agent_list_tactics", - * "arguments": { - * "outcomeAgentId": "example_id_123" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'outcomes_agent_list_tactics'; - arguments: components['schemas']['OutcomesAgentListTacticsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['OutcomesAgentListTactics']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Create service token - * @description Create a new service token for API authentication. Returns the full token which should be stored securely as it cannot be retrieved later. - */ - service_token_create: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_create */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_create", - * "arguments": { - * "name": "Example Name" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_create'; - arguments: components['schemas']['CreateServiceTokenInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['CreateServiceTokenOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * List service tokens - * @description List all service tokens for the authenticated customer. Secrets are never returned, only metadata. - */ - service_token_list: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_list */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_list", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_list'; - arguments: components['schemas']['ListServiceTokensInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['ListServiceTokensOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get service token - * @description Get detailed information about a specific service token. The secret is never returned. - */ - service_token_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_get", - * "arguments": { - * "id": "1234567890" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_get'; - arguments: components['schemas']['GetServiceTokenInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['GetServiceTokenOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Update service token - * @description Update a service token. Only name, description, and expiration can be modified. - */ - service_token_update: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_update */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_update", - * "arguments": { - * "id": "1234567890" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_update'; - arguments: components['schemas']['UpdateServiceTokenInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['UpdateServiceTokenOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Archive service token - * @description Archive (soft delete) a service token. This immediately invalidates the token for authentication. - */ - service_token_archive: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for service_token_archive */ - requestBody: { - content: { - /** - * @example { - * "tool": "service_token_archive", - * "arguments": { - * "id": "1234567890" - * } - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'service_token_archive'; - arguments: components['schemas']['ArchiveServiceTokenInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['ArchiveServiceTokenOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get customer info - * @description Get detailed information about a customer from the core database. - */ - customer_get: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for customer_get */ - requestBody: { - content: { - /** - * @example { - * "tool": "customer_get", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'customer_get'; - arguments: components['schemas']['GetCustomerInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['GetCustomerOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; - /** - * Get customer seats - * @description Get all seats associated with a customer from the core database. - */ - customer_get_seats: { - parameters: { - header: { - /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ - 'mcp-session-id': string; - }; - }; - /** @description Request body for customer_get_seats */ - requestBody: { - content: { - /** - * @example { - * "tool": "customer_get_seats", - * "arguments": {} - * } - */ - 'application/json': { - /** @enum {string} */ - tool: 'customer_get_seats'; - arguments: components['schemas']['GetCustomerSeatsInput']; - }; - }; - }; - responses: { - /** @description Successful response */ - 200: { - content: { - 'application/json': { - content: components['schemas']['MCPContent'][]; - structuredContent: components['schemas']['GetCustomerSeatsOutput']; - }; - }; - }; - /** @description Bad request */ - 400: { - content: { - 'application/json': components['schemas']['BadRequest']; - }; - }; - /** @description Unauthorized */ - 401: { - content: { - 'application/json': components['schemas']['Unauthorized']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['InternalError']; - }; - }; - }; - }; -} diff --git a/src/webhook-server.ts b/src/webhook-server.ts index 13d6e49..935f0c7 100644 --- a/src/webhook-server.ts +++ b/src/webhook-server.ts @@ -1,3 +1,4 @@ +import { timingSafeEqual } from 'crypto'; import express from 'express'; import type { Express, Request, Response, NextFunction } from 'express'; import { Server } from 'http'; @@ -26,24 +27,32 @@ export class WebhookServer { this.app = express(); this.handlers = new Map(); this.config = { - port: config.port || 3000, - path: config.path || '/webhooks', - secret: config.secret || '', + port: config.port ?? 3000, + path: config.path ?? '/webhooks', + secret: config.secret ?? '', }; + if (!this.config.secret) { + console.warn('WebhookServer: No secret configured. Webhook endpoint is unauthenticated.'); + } + this.setupMiddleware(); this.setupRoutes(); } private setupMiddleware(): void { - this.app.use(express.json()); + this.app.use(express.json({ limit: '10kb' })); if (this.config.secret) { this.app.use((req: Request, res: Response, next: NextFunction) => { const authHeader = req.headers['authorization']; const expectedAuth = `Bearer ${this.config.secret}`; - if (authHeader !== expectedAuth) { + if ( + !authHeader || + authHeader.length !== expectedAuth.length || + !timingSafeEqual(Buffer.from(authHeader), Buffer.from(expectedAuth)) + ) { res.status(401).json({ error: 'Unauthorized' }); return; } @@ -56,12 +65,12 @@ export class WebhookServer { private setupRoutes(): void { this.app.post(this.config.path, async (req: Request, res: Response) => { try { - const event: WebhookEvent = req.body; - - if (!event.type) { - res.status(400).json({ error: 'Missing event type' }); + const body = req.body; + if (!body || typeof body !== 'object' || typeof body.type !== 'string' || !body.type) { + res.status(400).json({ error: 'Invalid webhook event format' }); return; } + const event = body as WebhookEvent; const handlers = this.handlers.get(event.type) || []; const allHandlers = this.handlers.get('*') || []; @@ -73,7 +82,10 @@ export class WebhookServer { res.status(200).json({ success: true }); } catch (error) { - console.error('Webhook handler error:', error); + console.error( + 'Webhook handler error:', + error instanceof Error ? error.message : 'Unknown error' + ); res.status(500).json({ error: 'Internal server error' }); } }); @@ -87,7 +99,9 @@ export class WebhookServer { if (!this.handlers.has(eventType)) { this.handlers.set(eventType, []); } - this.handlers.get(eventType)!.push(handler); + const handlers = this.handlers.get(eventType) ?? []; + handlers.push(handler); + this.handlers.set(eventType, handlers); } off(eventType: string, handler?: WebhookHandler): void { @@ -106,12 +120,15 @@ export class WebhookServer { } start(): Promise { - return new Promise((resolve) => { + return new Promise((resolve, reject) => { this.server = this.app.listen(this.config.port, () => { console.log(`Webhook server listening on port ${this.config.port}`); console.log(`Webhook endpoint: http://localhost:${this.config.port}${this.config.path}`); resolve(); }); + this.server.on('error', (err) => { + reject(err); + }); }); }