{
  "openapi": "3.1.0",
  "info": {
    "title": "iris API",
    "version": "2.19.0",
    "description": "iris - the ai messenger. manage campaigns, contacts, conversations, content generation, analytics, and more.",
    "contact": {
      "name": "iris",
      "url": "https://www.iris-ai.dev"
    },
    "x-guidance": "iris runs multi-channel AI outreach campaigns (email, Twitter DM, Instagram DM). most endpoints require an API key (Authorization: Bearer is_live_...) - create one at https://www.iris-ai.dev/settings/api. POST /campaigns is the only paid operation: x402 wallets pay $2.25 USDC on Base per campaign; MPP agents buy a 5-credit pack for $12.00 at POST /agent/credits ($2.40 effective per campaign). 1 credit covers contact discovery, AI drafting, and 240 message sends. iris does not offer an x402 free tier. see https://www.iris-ai.dev/docs#agent-payments for the full payment flow and https://api.iris-ai.dev/llms.txt for product context."
  },
  "x-discovery": {
    "ownershipProofs": [
      "domain:api.iris-ai.dev",
      "wellknown:https://api.iris-ai.dev/.well-known/x402"
    ]
  },
  "x-service-info": {
    "categories": [
      "outreach",
      "marketing",
      "messaging",
      "automation"
    ],
    "docs": {
      "homepage": "https://www.iris-ai.dev",
      "apiReference": "https://www.iris-ai.dev/docs",
      "llms": "https://api.iris-ai.dev/llms.txt"
    }
  },
  "servers": [
    {
      "url": "https://api.iris-ai.dev",
      "description": "production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "authentication",
      "description": "verify your API key and view its metadata."
    },
    {
      "name": "API keys",
      "description": "programmatically manage API keys. all routes in this group (except `/keys/me`) require an API key with the `admin` scope. `/keys/me` returns metadata for the currently-authenticated key and works without any scope."
    },
    {
      "name": "campaigns",
      "description": "create and manage outreach campaigns."
    },
    {
      "name": "audiences",
      "description": "your reusable audience library - target profiles created once (manually or AI-generated from a product) and attached to any campaign. attaching copies the profile into the campaign, so campaign edits never touch the library master."
    },
    {
      "name": "contacts",
      "description": "manage contacts and import leads."
    },
    {
      "name": "conversations",
      "description": "manage conversations across all channels."
    },
    {
      "name": "messages",
      "description": "manage message approval workflow and sending."
    },
    {
      "name": "AI",
      "description": "AI-powered content generation and analysis."
    },
    {
      "name": "discovery",
      "description": "search for and discover new contacts."
    },
    {
      "name": "analytics",
      "description": "campaign performance metrics and reporting."
    },
    {
      "name": "billing",
      "description": "view billing plans and subscription information."
    },
    {
      "name": "autopilot",
      "description": "configure the autonomous outreach loop - discovery top-ups and drafts on a standing campaign, review-only."
    },
    {
      "name": "channels",
      "description": "manage connected accounts and multi-channel messaging."
    },
    {
      "name": "notifications",
      "description": "manage user notifications."
    },
    {
      "name": "webhooks",
      "description": "manage webhook endpoints for receiving real-time event notifications. all routes in this group require an API key with the `admin` scope (round-6 audit closed a privilege-escalation gap where a non-admin key could create or rotate webhooks)."
    },
    {
      "name": "agent credits",
      "description": "credit-based payments for AI agents using x402 (USDC on Base) or MPP (Stripe). 1 credit = 1 campaign (30 contacts, 240 messages, AI drafting bundled in). no subscription required."
    },
    {
      "name": "changelog",
      "description": "machine-readable release history - public, no API key required."
    }
  ],
  "paths": {
    "/keys/me": {
      "get": {
        "tags": [
          "authentication"
        ],
        "summary": "get information about the currently authenticated API key",
        "operationId": "getCurrentKey",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiKey"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "user_id": "uuid",
                    "name": "production",
                    "key_prefix": "is_live_a1b2c3d4",
                    "scopes": [
                      "*"
                    ],
                    "last_used_at": "2024-01-15T10:30:00Z",
                    "expires_at": null,
                    "revoked_at": null,
                    "created_at": "2024-01-01T00:00:00Z",
                    "updated_at": "2024-01-15T10:30:00Z"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/keys": {
      "get": {
        "tags": [
          "API keys"
        ],
        "summary": "list all API keys for your account",
        "operationId": "listKeys",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKey"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "uuid",
                      "user_id": "uuid",
                      "name": "production",
                      "key_prefix": "is_live_a1b2c3d4",
                      "scopes": [
                        "*"
                      ],
                      "last_used_at": "2024-01-15T10:30:00Z",
                      "expires_at": null,
                      "revoked_at": null,
                      "created_at": "2024-01-01T00:00:00Z",
                      "updated_at": "2024-01-15T10:30:00Z"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total": 1,
                    "total_pages": 1
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ]
      },
      "post": {
        "tags": [
          "API keys"
        ],
        "summary": "create a new API key. the raw key is only returned once.",
        "operationId": "createKey",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateApiKeyResponse"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "user_id": "uuid",
                    "name": "staging",
                    "key_prefix": "is_live_e5f6g7h8",
                    "key": "is_live_e5f6g7h8a9b0c1d2e3f4g5h6i7j8k9l0m1n2o3p4",
                    "scopes": [
                      "read"
                    ],
                    "last_used_at": null,
                    "expires_at": null,
                    "revoked_at": null,
                    "created_at": "2024-01-15T10:30:00Z",
                    "updated_at": "2024-01-15T10:30:00Z"
                  }
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "key name (1-100 characters)"
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "permission scopes (any of: read, write, generate, send, admin). defaults to [\"*\"] for full access. DELETE routes gate on write (soft-deletes) - there is no delete scope"
                  },
                  "expires_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "optional expiration date"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "description": "the raw key value is only returned on creation - store it securely"
      }
    },
    "/keys/{id}": {
      "patch": {
        "tags": [
          "API keys"
        ],
        "summary": "rename an API key. only the display label is updated; the secret, scopes, and expiry are untouched.",
        "operationId": "updateKey",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiKey"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "name": "renamed key",
                    "key_prefix": "is_live_abcd",
                    "scopes": [
                      "read",
                      "write"
                    ],
                    "last_used_at": "2026-04-29T12:00:00Z",
                    "expires_at": null,
                    "revoked_at": null,
                    "created_at": "2026-04-01T12:00:00Z",
                    "updated_at": "2026-04-29T13:00:00Z"
                  }
                }
              }
            }
          },
          "404": {
            "description": "APIKEY_006: API key not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "new display name (1-100 chars)"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "API keys"
        ],
        "summary": "revoke an API key. this action is irreversible.",
        "operationId": "deleteKey",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "no content"
          },
          "404": {
            "description": "APIKEY_006: API key not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/keys/{id}/rotate": {
      "post": {
        "tags": [
          "API keys"
        ],
        "summary": "rotate an API key: revokes the old key and creates a new one with the same name and scopes. the new raw key is returned exactly once. update stored credentials immediately. the old key stops authenticating as soon as this returns. cannot rotate the key being used for the request itself (would lock the caller out mid-rotation).",
        "operationId": "createRotate",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateApiKeyResponse"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "name": "my integration",
                    "key_prefix": "is_live_xyz...",
                    "scopes": [
                      "read",
                      "write",
                      "generate",
                      "send"
                    ],
                    "last_used_at": null,
                    "expires_at": null,
                    "revoked_at": null,
                    "created_at": "2026-05-07T12:00:00Z",
                    "updated_at": "2026-05-07T12:00:00Z",
                    "key": "is_live_xyz...thefullnewkeyshownonceonly"
                  }
                }
              }
            }
          },
          "404": {
            "description": "APIKEY_006: API key not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "SERVER_005: cannot rotate the API key currently being used",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "description": "the new key's `id` is different from the old `id`. update any stored references.\n\nthe underlying service makes the usage counter net-zero, so rotation never trips MAX_ACTIVE_KEYS_PER_USER even when the user is at the limit."
      }
    },
    "/campaigns": {
      "get": {
        "tags": [
          "campaigns"
        ],
        "summary": "list all campaigns",
        "operationId": "listCampaigns",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Campaign"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "uuid",
                      "user_id": "uuid",
                      "name": "Q1 outreach",
                      "status": "active",
                      "objective_type": "product_promotion",
                      "product_name": "Acme Widget",
                      "product_url": "https://acme.example.com",
                      "product_description": null,
                      "follow_up_enabled": true,
                      "follow_up_max_count": 2,
                      "follow_up_delay_days": 3,
                      "keywords": [
                        "coffee shop",
                        "cafe"
                      ],
                      "venue_types": [],
                      "outreach_channels": [
                        "email"
                      ],
                      "location": "Brooklyn, NY",
                      "radius_miles": 25,
                      "min_budget": null,
                      "max_budget": null,
                      "dynamic_fields": {},
                      "created_at": "2024-01-15T10:30:00Z",
                      "updated_at": "2024-01-15T10:30:00Z"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total": 1,
                    "total_pages": 1
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "filter by status (draft, active, paused, completed, deleted)",
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "post": {
        "tags": [
          "campaigns"
        ],
        "summary": "create a new campaign",
        "operationId": "createCampaign",
        "security": [
          {
            "apiKey": []
          },
          {
            "agentPaymentAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Campaign"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "name": "spring outreach",
                    "objective_type": "product_promotion",
                    "status": "draft",
                    "created_at": "2024-01-15T10:30:00Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "SERVER_002: campaign needs goal, product, or sender context before drafts can be generated (non-venue campaign missing sender context)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "payment required: agent payment auth (x402 or MPP). campaign creation costs $2.25 via x402 (crypto) or 1 credit ($2.40 effective via MPP credit pack).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "PAYMENT_005"
                        },
                        "message": {
                          "type": "string",
                          "example": "insufficient credits: pay $2.25 USDC per campaign (x402) or buy a 5-credit pack for $12.00 (MPP)"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    },
                    "x402": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "integer",
                          "example": 2
                        },
                        "scheme": {
                          "type": "string",
                          "example": "exact"
                        },
                        "network": {
                          "type": "string",
                          "example": "eip155:8453"
                        },
                        "asset": {
                          "type": "string",
                          "example": "USDC"
                        },
                        "amount": {
                          "type": "string",
                          "example": "2.25"
                        },
                        "receiver": {
                          "type": "string"
                        },
                        "resource": {
                          "type": "string"
                        }
                      }
                    },
                    "mpp": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "integer",
                          "example": 1
                        },
                        "method": {
                          "type": "string",
                          "example": "stripe"
                        },
                        "intent": {
                          "type": "string",
                          "example": "charge"
                        },
                        "currency": {
                          "type": "string",
                          "example": "usd"
                        },
                        "amount_cents": {
                          "type": "integer",
                          "example": 1200
                        },
                        "resource": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "CAMP_009: campaign limit reached for billing period",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "campaign name (1-200 chars)"
                  },
                  "objective_type": {
                    "type": "string",
                    "description": "free-text 2-5 word goal summary (e.g. 'venue_host', 'promote my coffee shop'). discovery routing uses target_profile_type, not this field."
                  },
                  "goal_description": {
                    "type": "string",
                    "description": "what the campaign should achieve (max 2000 chars) - counts as sender context"
                  },
                  "product_name": {
                    "type": "string",
                    "description": "product name (max 200 chars) - counts as sender context"
                  },
                  "product_url": {
                    "type": "string",
                    "description": "product URL for AI analysis (max 2000 chars)"
                  },
                  "product_description": {
                    "type": "string",
                    "description": "product description for AI context (max 5000 chars) - counts as sender context"
                  },
                  "dynamic_fields": {
                    "type": "object",
                    "description": "freeform context key-values. sender keys (sender_company, sender_role, goal_description, product_description, product_name, product_url, target_audience) count as sender context"
                  },
                  "location": {
                    "type": "string",
                    "description": "location to target"
                  },
                  "location_lat": {
                    "type": "number",
                    "description": "location latitude"
                  },
                  "location_lng": {
                    "type": "number",
                    "description": "location longitude"
                  },
                  "radius_miles": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "description": "search radius in miles",
                    "default": 10
                  },
                  "keywords": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "discovery keywords"
                  },
                  "venue_types": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "venue types for venue objectives (e.g. bar, club)"
                  },
                  "max_results": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 500,
                    "description": "maximum contacts to discover",
                    "default": 50
                  },
                  "followup_days": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "days after initial outreach to send follow-ups (e.g. [3, 7, 14])"
                  },
                  "outreach_channels": {
                    "type": "string",
                    "enum": [
                      "email",
                      "instagram",
                      "twitter"
                    ],
                    "description": "channels to send outreach on",
                    "default": "[\"email\"]"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "active",
                      "paused",
                      "completed"
                    ],
                    "description": "initial campaign status",
                    "default": "\"draft\""
                  },
                  "selected_venues": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    },
                    "description": "discovered venue/contact objects to import into the campaign at creation"
                  },
                  "min_budget": {
                    "type": "number",
                    "description": "minimum budget (must not exceed max_budget)"
                  },
                  "max_budget": {
                    "type": "number",
                    "description": "maximum budget"
                  },
                  "event_date": {
                    "type": "string",
                    "description": "event date (venue/event objectives)"
                  },
                  "expected_attendees": {
                    "type": "integer",
                    "description": "expected attendee count"
                  },
                  "time_slot_start": {
                    "type": "string",
                    "description": "event time slot start"
                  },
                  "time_slot_end": {
                    "type": "string",
                    "description": "event time slot end"
                  }
                },
                "required": [
                  "name",
                  "objective_type"
                ]
              }
            }
          }
        },
        "description": "sender context is required for non-venue campaigns: set at least one of goal_description, product_name, product_description, or a sender key inside dynamic_fields (sender_company, sender_role, target_audience, ...). objective_type values starting with 'venue_' are exempt - they carry structured venue fields instead.\n\nagent payments: this is the only paid operation in the public API for agents. x402 agents pay $2.25 USDC per campaign. read the PAYMENT-REQUIRED header from the 402, sign it, and replay with a PAYMENT-SIGNATURE header (x402 v2). MPP agents deduct 1 credit from a credit pack ($2.40 effective). discovery, AI drafting, and message sends run automatically inside the campaign workflow as internal QStash jobs. agents never call /discovery/search, /ai/generate, or /channels/send directly (those endpoints require an API key).\n\niris does not offer an x402 free tier - every agent campaign requires payment.\n\nsee the agent-payments and credit-packs sections for the full 402 challenge flow.",
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "2.250000"
          },
          "protocols": [
            {
              "x402": {}
            },
            {
              "mpp": {
                "method": "stripe",
                "intent": "charge",
                "currency": "usd"
              }
            }
          ]
        }
      }
    },
    "/campaigns/{id}": {
      "get": {
        "tags": [
          "campaigns"
        ],
        "summary": "get a specific campaign with full details",
        "operationId": "getCampaign",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Campaign"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      },
      "patch": {
        "tags": [
          "campaigns"
        ],
        "summary": "update a campaign",
        "operationId": "updateCampaign",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Campaign"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "CAMP_008: invalid status transition",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "campaign name (1-200 chars)"
                  },
                  "objective_type": {
                    "type": "string",
                    "description": "free-text goal summary"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "scheduled",
                      "active",
                      "paused",
                      "completed",
                      "deleted"
                    ],
                    "description": "campaign status. transitions are validated: draft → active, active → paused/completed, paused → active/completed"
                  },
                  "product_name": {
                    "type": "string",
                    "description": "product name (max 200 chars)"
                  },
                  "product_url": {
                    "type": "string",
                    "description": "product URL (max 2000 chars)"
                  },
                  "product_description": {
                    "type": "string",
                    "description": "product description (max 5000 chars)"
                  },
                  "goal_description": {
                    "type": "string",
                    "description": "what the campaign should achieve (max 2000 chars)"
                  },
                  "dynamic_fields": {
                    "type": "object",
                    "description": "freeform context key-values (sender_company, sender_role, target_audience, ...)"
                  },
                  "min_budget": {
                    "type": "number",
                    "description": "minimum budget (must not exceed max_budget)"
                  },
                  "max_budget": {
                    "type": "number",
                    "description": "maximum budget"
                  },
                  "location": {
                    "type": "string",
                    "description": "location to target"
                  },
                  "location_lat": {
                    "type": "number",
                    "description": "location latitude"
                  },
                  "location_lng": {
                    "type": "number",
                    "description": "location longitude"
                  },
                  "radius_miles": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "description": "search radius in miles"
                  },
                  "keywords": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "discovery keywords"
                  },
                  "venue_types": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "venue types"
                  },
                  "max_results": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 500,
                    "description": "maximum contacts to discover"
                  },
                  "followup_days": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "days after initial outreach to send follow-ups"
                  },
                  "outreach_channels": {
                    "type": "string",
                    "enum": [
                      "email",
                      "instagram",
                      "twitter"
                    ],
                    "description": "channels to send outreach on"
                  },
                  "event_date": {
                    "type": "string",
                    "description": "event date (venue/event objectives)"
                  },
                  "expected_attendees": {
                    "type": "integer",
                    "description": "expected attendee count"
                  },
                  "time_slot_start": {
                    "type": "string",
                    "description": "event time slot start"
                  },
                  "time_slot_end": {
                    "type": "string",
                    "description": "event time slot end"
                  },
                  "start_date": {
                    "type": "string",
                    "description": "campaign start date (must not be after end_date)"
                  },
                  "end_date": {
                    "type": "string",
                    "description": "campaign end date"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "campaigns"
        ],
        "summary": "soft-delete a campaign (sets status to 'deleted')",
        "operationId": "deleteCampaign",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "no content"
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/campaigns/{id}/contacts": {
      "get": {
        "tags": [
          "campaigns"
        ],
        "summary": "list contacts in a campaign",
        "operationId": "listCampaignContacts",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CampaignContact"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "uuid",
                      "user_id": "uuid",
                      "email": "jane@example.com",
                      "first_name": "Jane",
                      "last_name": "Smith",
                      "company_name": "Acme Inc",
                      "job_title": "Head of Marketing",
                      "phone": null,
                      "website": null,
                      "tags": [
                        "lead",
                        "enterprise"
                      ],
                      "enrichment_data": null,
                      "created_at": "2024-01-15T10:30:00Z",
                      "updated_at": "2024-01-15T10:30:00Z",
                      "deleted_at": null,
                      "campaign_contact_id": "uuid",
                      "campaign_contact_status": "active",
                      "added_at": "2024-01-15T10:30:00Z"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total": 1,
                    "total_pages": 1
                  }
                }
              }
            }
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "filter by contact status",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/campaigns/{id}/usage": {
      "get": {
        "tags": [
          "campaigns"
        ],
        "summary": "get campaign usage statistics",
        "operationId": "getCampaignUsage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/CampaignUsage"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "campaign_id": "uuid",
                    "status": "active",
                    "total_contacts": 150,
                    "total_conversations": 42,
                    "delivery_status": {
                      "sent": 42,
                      "delivered": 40,
                      "opened": 28,
                      "clicked": 12
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/campaigns/{id}/analyze": {
      "post": {
        "tags": [
          "campaigns"
        ],
        "summary": "trigger AI product analysis for a campaign",
        "operationId": "analyzeCampaign",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Campaign"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "AI_004: AI rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "description": "analyzes the campaign's product URL/description and generates target profiles\n\nreturns immediately - analysis runs asynchronously"
      }
    },
    "/campaigns/{id}/target-profiles": {
      "get": {
        "tags": [
          "campaigns"
        ],
        "summary": "list target profiles for a campaign",
        "operationId": "listTargetProfiles",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TargetProfile"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "uuid",
                      "campaign_id": "uuid",
                      "name": "SaaS founders",
                      "profile_type": "b2b_professional",
                      "fit_score": 85,
                      "job_titles": [
                        "CEO",
                        "CTO",
                        "founder"
                      ],
                      "industries": [
                        "technology",
                        "SaaS"
                      ],
                      "discovery_keywords": [
                        "saas founder",
                        "tech startup"
                      ],
                      "recommended_channels": []
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      },
      "post": {
        "tags": [
          "campaigns"
        ],
        "summary": "create a target profile for a campaign",
        "operationId": "createTargetProfile",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/TargetProfile"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "profile name (max 200 chars)"
                  },
                  "profile_type": {
                    "type": "string",
                    "enum": [
                      "local_business",
                      "content_creator",
                      "influencer",
                      "b2b_professional",
                      "ecommerce",
                      "saas_company",
                      "agency",
                      "freelancer",
                      "other"
                    ],
                    "description": "target profile type"
                  },
                  "description": {
                    "type": "string",
                    "description": "who this profile targets (max 2000 chars)"
                  },
                  "fit_score": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "description": "how well this profile fits the campaign"
                  },
                  "job_titles": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "target job titles"
                  },
                  "industries": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "target industries"
                  },
                  "company_sizes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "target company sizes (e.g. '1-10')"
                  },
                  "pain_points": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "problems this profile feels"
                  },
                  "buying_signals": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "signals they're ready to buy"
                  },
                  "discovery_sources": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "discovery sources to search (e.g. google_maps, instagram)"
                  },
                  "discovery_keywords": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "keywords for contact discovery"
                  },
                  "outreach_angle": {
                    "type": "string",
                    "description": "the hook messages should lead with (max 2000 chars)"
                  }
                },
                "required": [
                  "name",
                  "profile_type"
                ]
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}/target-profiles/{profileId}": {
      "delete": {
        "tags": [
          "campaigns"
        ],
        "summary": "delete a target profile",
        "operationId": "deleteTargetProfile",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "no content"
          },
          "404": {
            "description": "CAMP_001: campaign or profile not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          },
          {
            "name": "profileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "profileId"
          }
        ]
      }
    },
    "/audiences": {
      "get": {
        "tags": [
          "audiences"
        ],
        "summary": "list your audience library (newest first)",
        "operationId": "listAudiences",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AudienceProfile"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "uuid",
                      "name": "indie coffee shops",
                      "description": "independent cafes with an active local following",
                      "profile_type": "local_business",
                      "fit_score": 82,
                      "job_titles": [
                        "owner",
                        "general manager"
                      ],
                      "industries": [
                        "food and beverage",
                        "hospitality"
                      ],
                      "company_sizes": [
                        "1-10"
                      ],
                      "pain_points": [
                        "slow weekday mornings",
                        "no online ordering"
                      ],
                      "buying_signals": [
                        "hiring baristas",
                        "new location announcement"
                      ],
                      "discovery_sources": [
                        "google_maps",
                        "instagram"
                      ],
                      "discovery_keywords": [
                        "specialty coffee",
                        "third wave cafe"
                      ],
                      "outreach_angle": "help them turn quiet weekday mornings into regulars",
                      "contacts_discovered": 24,
                      "created_at": "2026-07-01T00:00:00Z",
                      "updated_at": "2026-07-09T14:30:00Z"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total": 1,
                    "total_pages": 1
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ]
      },
      "post": {
        "tags": [
          "audiences"
        ],
        "summary": "create a library profile manually. names are unique per library (case-insensitive).",
        "operationId": "createAudience",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "201": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AudienceProfile"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "name": "indie coffee shops",
                    "description": "independent cafes with an active local following",
                    "profile_type": "local_business",
                    "fit_score": 82,
                    "job_titles": [
                      "owner",
                      "general manager"
                    ],
                    "industries": [
                      "food and beverage"
                    ],
                    "company_sizes": [],
                    "pain_points": [
                      "slow weekday mornings"
                    ],
                    "buying_signals": [],
                    "discovery_sources": [],
                    "discovery_keywords": [
                      "specialty coffee"
                    ],
                    "outreach_angle": "help them turn quiet weekday mornings into regulars",
                    "contacts_discovered": 0,
                    "created_at": "2026-07-09T14:30:00Z",
                    "updated_at": "2026-07-09T14:30:00Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "SERVER_002: an audience with this name already exists",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "SERVER_005: validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "audience name (1-100 chars)"
                  },
                  "profile_type": {
                    "type": "string",
                    "enum": [
                      "local_business",
                      "content_creator",
                      "influencer",
                      "b2b_professional",
                      "ecommerce",
                      "saas_company",
                      "agency",
                      "freelancer",
                      "other"
                    ],
                    "description": "target profile type"
                  },
                  "description": {
                    "type": "string",
                    "description": "who this audience is (max 500 chars)"
                  },
                  "fit_score": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "description": "how well this audience fits your product"
                  },
                  "job_titles": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "target job titles (max 10)"
                  },
                  "industries": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "target industries (max 10)"
                  },
                  "company_sizes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "target company sizes (max 10, e.g. '1-10')"
                  },
                  "pain_points": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "problems they feel (max 10)"
                  },
                  "buying_signals": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "signals they're ready to buy (max 10)"
                  },
                  "discovery_sources": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "discovery sources to search (max 10, e.g. google_maps, instagram)"
                  },
                  "discovery_keywords": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "keywords for contact discovery (max 10)"
                  },
                  "outreach_angle": {
                    "type": "string",
                    "description": "the hook messages should lead with (max 500 chars)"
                  }
                },
                "required": [
                  "name",
                  "profile_type"
                ]
              }
            }
          }
        }
      }
    },
    "/audiences/{id}": {
      "get": {
        "tags": [
          "audiences"
        ],
        "summary": "get one library profile",
        "operationId": "getAudience",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AudienceProfile"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "name": "indie coffee shops",
                    "description": "independent cafes with an active local following",
                    "profile_type": "local_business",
                    "fit_score": 82,
                    "job_titles": [
                      "owner",
                      "general manager"
                    ],
                    "industries": [
                      "food and beverage"
                    ],
                    "company_sizes": [
                      "1-10"
                    ],
                    "pain_points": [
                      "slow weekday mornings"
                    ],
                    "buying_signals": [
                      "hiring baristas"
                    ],
                    "discovery_sources": [
                      "google_maps"
                    ],
                    "discovery_keywords": [
                      "specialty coffee"
                    ],
                    "outreach_angle": "help them turn quiet weekday mornings into regulars",
                    "contacts_discovered": 24,
                    "created_at": "2026-07-01T00:00:00Z",
                    "updated_at": "2026-07-09T14:30:00Z"
                  }
                }
              }
            }
          },
          "404": {
            "description": "SERVER_003: audience not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      },
      "delete": {
        "tags": [
          "audiences"
        ],
        "summary": "delete a library profile. campaigns it was attached to keep their copy (those use the campaign target-profile DELETE).",
        "operationId": "deleteAudience",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "no content"
          },
          "404": {
            "description": "SERVER_003: audience not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/audiences/{id}/attach": {
      "post": {
        "tags": [
          "audiences"
        ],
        "summary": "copy a library profile into a campaign. the response is the campaign's own copy (a TargetProfile) - editing it never touches the library master. if the campaign already has a profile with the same name, the existing copy is returned instead.",
        "operationId": "attachAudience",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "201": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/TargetProfile"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "campaign_id": "uuid",
                    "user_id": "uuid",
                    "name": "indie coffee shops",
                    "profile_type": "local_business",
                    "fit_score": 82,
                    "job_titles": [
                      "owner",
                      "general manager"
                    ],
                    "industries": [
                      "food and beverage"
                    ],
                    "pain_points": [
                      "slow weekday mornings"
                    ],
                    "buying_signals": [
                      "hiring baristas"
                    ],
                    "discovery_keywords": [
                      "specialty coffee"
                    ],
                    "recommended_channels": [],
                    "created_at": "2026-07-09T14:30:00Z",
                    "updated_at": "2026-07-09T14:30:00Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "SERVER_002: campaign is completed or deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "SERVER_003: audience not found; CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "campaign_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "the campaign to attach to (must be yours and not completed or deleted)"
                  }
                },
                "required": [
                  "campaign_id"
                ]
              }
            }
          }
        }
      }
    },
    "/audiences/generate": {
      "post": {
        "tags": [
          "audiences"
        ],
        "summary": "AI-generate library profiles from a product (scrape + analysis). returns the created profiles; generated names already in your library are skipped, not overwritten. rate limited to 5 per hour.",
        "operationId": "generateAudiences",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "201": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AudienceProfile"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "uuid",
                      "name": "boutique fitness studios",
                      "description": "independent gyms and studios booking classes online",
                      "profile_type": "local_business",
                      "fit_score": 88,
                      "job_titles": [
                        "owner",
                        "studio manager"
                      ],
                      "industries": [
                        "fitness",
                        "wellness"
                      ],
                      "company_sizes": [
                        "1-10"
                      ],
                      "pain_points": [
                        "no-shows",
                        "manual scheduling"
                      ],
                      "buying_signals": [
                        "hiring front desk staff"
                      ],
                      "discovery_sources": [
                        "google_maps",
                        "instagram"
                      ],
                      "discovery_keywords": [
                        "boutique fitness",
                        "yoga studio"
                      ],
                      "outreach_angle": "cut no-shows with automated scheduling",
                      "contacts_discovered": 0,
                      "created_at": "2026-07-09T14:30:00Z",
                      "updated_at": "2026-07-09T14:30:00Z"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "BILLING_003: audience generation needs an active subscription",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "SERVER_005: validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "RATE_001: generation rate limit exceeded (5 per hour)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "generate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "product_name": {
                    "type": "string",
                    "description": "product name (1-200 chars)"
                  },
                  "product_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "product website - scraped for extra context"
                  },
                  "product_description": {
                    "type": "string",
                    "description": "what it does and who it's for (max 2000 chars)"
                  }
                },
                "required": [
                  "product_name"
                ]
              }
            }
          }
        }
      }
    },
    "/contacts": {
      "get": {
        "tags": [
          "contacts"
        ],
        "summary": "list all contacts",
        "operationId": "listContacts",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Contact"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "uuid",
                      "email": "jane@example.com",
                      "first_name": "Jane",
                      "last_name": "Smith",
                      "company_name": "Acme Inc",
                      "tags": [
                        "lead",
                        "enterprise"
                      ]
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total": 1,
                    "total_pages": 1
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "search by name or email",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "filter to contacts in a campaign",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      },
      "post": {
        "tags": [
          "contacts"
        ],
        "summary": "create a single contact. idempotent on email: if a contact with the same email already exists for this user, returns 201 with the existing record (merging any new fields you supply) instead of 409.",
        "operationId": "createContact",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Contact"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "CONTACT_009: contact limit reached for billing period",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "contact email - optional; contacts can exist with social handles only. dedup and merging key on it"
                  },
                  "first_name": {
                    "type": "string",
                    "description": "first name"
                  },
                  "last_name": {
                    "type": "string",
                    "description": "last name"
                  },
                  "company_name": {
                    "type": "string",
                    "description": "company name"
                  },
                  "instagram_handle": {
                    "type": "string",
                    "description": "instagram handle"
                  },
                  "twitter_handle": {
                    "type": "string",
                    "description": "twitter/x handle"
                  },
                  "tiktok_handle": {
                    "type": "string",
                    "description": "tiktok handle"
                  },
                  "notes": {
                    "type": "string",
                    "description": "freeform notes"
                  },
                  "discovery_method": {
                    "type": "string",
                    "description": "how the contact was discovered"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "tags for categorization"
                  },
                  "campaign_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "campaigns to associate with"
                  },
                  "campaign_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "single campaign to associate with (folded into campaign_ids server-side)"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/contacts/{id}": {
      "get": {
        "tags": [
          "contacts"
        ],
        "summary": "get a specific contact",
        "operationId": "getContact",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Contact"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CONTACT_001: contact not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      },
      "patch": {
        "tags": [
          "contacts"
        ],
        "summary": "update a contact",
        "operationId": "updateContact",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Contact"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CONTACT_001: contact not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "first_name": {
                    "type": "string",
                    "description": "first name"
                  },
                  "last_name": {
                    "type": "string",
                    "description": "last name"
                  },
                  "company_name": {
                    "type": "string",
                    "description": "company name"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "tags"
                  },
                  "instagram_handle": {
                    "type": "string",
                    "description": "instagram handle"
                  },
                  "twitter_handle": {
                    "type": "string",
                    "description": "twitter/x handle"
                  },
                  "tiktok_handle": {
                    "type": "string",
                    "description": "tiktok handle"
                  },
                  "campaign_ids_to_add": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "campaigns to add this contact to"
                  },
                  "campaign_ids_to_remove": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "campaigns to remove this contact from"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "contacts"
        ],
        "summary": "soft-delete a contact (sets deleted_at timestamp)",
        "operationId": "deleteContact",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "no content"
          },
          "404": {
            "description": "CONTACT_001: contact not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/contacts/bulk": {
      "post": {
        "tags": [
          "contacts"
        ],
        "summary": "bulk import contacts (up to 500 per request)",
        "operationId": "bulkCreateContacts",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/BulkContactImportResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "created": 46,
                    "updated": 2,
                    "failed": 2,
                    "contacts": [
                      {
                        "id": "uuid",
                        "user_id": "uuid",
                        "email": "jane@example.com",
                        "first_name": "Jane",
                        "last_name": "Smith",
                        "company_name": "Acme Inc",
                        "job_title": null,
                        "phone": null,
                        "website": null,
                        "tags": [],
                        "enrichment_data": null,
                        "created_at": "2024-01-15T10:30:00Z",
                        "updated_at": "2024-01-15T10:30:00Z",
                        "deleted_at": null
                      }
                    ],
                    "errors": [
                      {
                        "email": "bad@",
                        "error": "invalid email format"
                      }
                    ]
                  }
                }
              }
            }
          },
          "429": {
            "description": "CONTACT_009: contact limit reached for billing period",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contacts": {
                    "type": "array",
                    "description": "array of contact objects (same fields as POST /contacts - email optional; duplicates merged by email or social handle: instagram/twitter/tiktok, case-insensitive, @ stripped, including within one request - retried imports are idempotent)"
                  },
                  "campaign_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "campaign to associate contacts with"
                  }
                },
                "required": [
                  "contacts"
                ]
              }
            }
          }
        },
        "description": "duplicates are merged by email (counted as updated). max 500 contacts per request."
      },
      "delete": {
        "tags": [
          "contacts"
        ],
        "summary": "bulk soft-delete contacts by ID",
        "operationId": "bulkDeleteContacts",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/BulkContactDeleteResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "deletedCount": 12,
                    "affectedCampaignIds": [
                      "uuid"
                    ],
                    "totalArchivedConversations": 3
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "non-empty array of contact IDs to delete"
                  }
                },
                "required": [
                  "contact_ids"
                ]
              }
            }
          }
        },
        "description": "sets deleted_at on each contact - same soft-delete semantics as DELETE /contacts/:id."
      }
    },
    "/contacts/usage": {
      "get": {
        "tags": [
          "contacts"
        ],
        "summary": "get contact usage for the current billing period",
        "operationId": "getContactUsage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ContactUsage"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "total_contacts": 1240,
                    "period_contacts": 150,
                    "period_limit": 30,
                    "period_start": "2024-01-01T00:00:00Z",
                    "period_end": "2024-02-01T00:00:00Z"
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "description": "period_limit is per-campaign, not per-period. null on plans where the per-campaign cap is unlimited (admin/team plans).\n\nperiod_contacts counts contacts created in the current billing period; total_contacts is the lifetime count of non-deleted contacts on the account."
      }
    },
    "/contacts/{id}/conversations": {
      "get": {
        "tags": [
          "contacts"
        ],
        "summary": "get conversations for a specific contact",
        "operationId": "listContactConversations",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Conversation"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CONTACT_001: contact not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/contacts/{id}/handles": {
      "get": {
        "tags": [
          "contacts"
        ],
        "summary": "the contact's social handles with engagement metadata (profile_url, is_engageable, follower_count, engagement_rate). since 2.16.0 the contact responses also carry the plain instagram_handle/twitter_handle/tiktok_handle fields directly",
        "operationId": "listContactHandles",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ContactHandle"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "channel": "tiktok",
                      "handle": "creator.one",
                      "profile_url": "https://tiktok.com/@creator.one",
                      "is_engageable": true,
                      "follower_count": 120000,
                      "engagement_rate": 0.041
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CONTACT_001: contact not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "contact id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/conversations": {
      "get": {
        "tags": [
          "conversations"
        ],
        "summary": "list all conversations",
        "operationId": "listConversations",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Conversation"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "filter by status (active, archived, closed)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "filter by channel (email, instagram, twitter, tiktok)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "filter by campaign",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      },
      "post": {
        "tags": [
          "conversations"
        ],
        "summary": "find-or-create a conversation for a contact - the hub conversation by default, or the campaign-scoped thread when campaign_id is passed (the contact must be a member of that campaign)",
        "operationId": "createConversation",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "201": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Conversation"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "x-scope": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "the contact to converse with"
                  },
                  "campaign_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "scope to a campaign the contact belongs to. closes the activation-order gap: campaign threads no longer depend on drafting having run"
                  }
                },
                "required": [
                  "contact_id"
                ]
              }
            }
          }
        },
        "description": "idempotent: returns the existing conversation for the requested scope if one exists\n\nadd messages via POST /conversations/:id/messages - pending-approval statuses land drafts in the review queue"
      }
    },
    "/conversations/{id}": {
      "get": {
        "tags": [
          "conversations"
        ],
        "summary": "get a conversation with its contact and full message thread",
        "operationId": "getConversation",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ConversationDetail"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "campaign_id": "uuid",
                    "contact_id": "uuid",
                    "user_id": "uuid",
                    "channel": "email",
                    "status": "active",
                    "metadata": null,
                    "contacts": {
                      "id": "uuid",
                      "full_name": "Jane Smith",
                      "email": "jane@example.com",
                      "company_name": "Acme Inc"
                    },
                    "messages": [
                      {
                        "id": "uuid",
                        "conversation_id": "uuid",
                        "direction": "outbound",
                        "channel": "email",
                        "content": "Hi Jane, ...",
                        "status": "sent",
                        "metadata": null,
                        "created_at": "2024-01-15T10:30:00Z",
                        "updated_at": "2024-01-15T10:30:00Z"
                      }
                    ],
                    "created_at": "2024-01-15T10:30:00Z",
                    "updated_at": "2024-01-15T10:30:00Z"
                  }
                }
              }
            }
          },
          "404": {
            "description": "CONVERSATION_001: conversation not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/conversations/{id}/messages": {
      "get": {
        "tags": [
          "conversations"
        ],
        "summary": "get messages for a conversation",
        "operationId": "listConversationMessages",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CONVERSATION_001: conversation not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      },
      "post": {
        "tags": [
          "conversations"
        ],
        "summary": "create a message in a conversation",
        "operationId": "createConversationMessage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "201": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateMessageResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CONVERSATION_001: conversation not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "type": "string",
                    "description": "message content"
                  },
                  "direction": {
                    "type": "string",
                    "description": "one of: inbound, outbound"
                  },
                  "status": {
                    "type": "string",
                    "description": "one of: draft, queued, sending, pending_approval, sent, delivered, failed, bounced, rejected"
                  },
                  "channel": {
                    "type": "string",
                    "description": "one of: email, twitter, instagram, tiktok (tiktok is manual-send: drafts + CRM recording only, no API delivery)"
                  },
                  "platform_recipient_id": {
                    "type": "string",
                    "description": "platform recipient id (twitter/instagram channels)"
                  }
                },
                "required": [
                  "content",
                  "direction",
                  "status",
                  "channel"
                ]
              }
            }
          }
        },
        "description": "status pending_approval places the message in the human review queue instead of sending\n\ninbound messages fire the conversation.reply_received webhook event"
      }
    },
    "/conversations/{id}/read": {
      "post": {
        "tags": [
          "conversations"
        ],
        "summary": "mark a conversation as read",
        "operationId": "markConversationRead",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/MarkConversationReadResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "unread_count": 0,
                    "contact_id": "uuid",
                    "already_read": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "CONVERSATION_001: conversation not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/conversations/engagement": {
      "get": {
        "tags": [
          "conversations"
        ],
        "summary": "get engagement metrics across conversations",
        "operationId": "getEngagement",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/EngagementMetrics"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "total": 250,
                    "unread": 18,
                    "by_status": {
                      "active": 42,
                      "archived": 8,
                      "closed": 200
                    },
                    "by_channel": {
                      "email": 210,
                      "twitter": 25,
                      "instagram": 15
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read"
      }
    },
    "/messages/pending": {
      "get": {
        "tags": [
          "messages"
        ],
        "summary": "list messages pending approval",
        "operationId": "listPendingMessages",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PendingMessage"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "filter by queue status (pending, approved, rejected, sending, sent, failed, revising)",
            "schema": {
              "type": "string",
              "default": "pending"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "filter by channel (email, twitter, instagram, tiktok)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "filter by campaign",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/messages/{id}/approve": {
      "post": {
        "tags": [
          "messages"
        ],
        "summary": "approve a pending message for sending",
        "operationId": "approveMessage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApproveMessageResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "MESSAGE_005: message not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "MESSAGE_004: message already approved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "send",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/messages/{id}/reject": {
      "post": {
        "tags": [
          "messages"
        ],
        "summary": "reject a pending message",
        "operationId": "rejectMessage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/RejectMessageResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "MESSAGE_005: message not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "send",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "rejection reason"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/messages/{id}/retry": {
      "post": {
        "tags": [
          "messages"
        ],
        "summary": "retry a failed message",
        "operationId": "retryMessage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/RetryMessageResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "MESSAGE_005: message not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "send",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/messages/{id}/feedback": {
      "post": {
        "tags": [
          "messages"
        ],
        "summary": "submit feedback to revise a message with AI",
        "operationId": "submitMessageFeedback",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/MessageFeedbackResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "MESSAGE_005: message not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "AI_004: AI rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "send",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "feedback": {
                    "type": "string",
                    "description": "revision instructions (e.g. 'make it more casual and shorter')"
                  },
                  "approval_queue_id": {
                    "type": "string",
                    "description": "approval queue item to revise (when the draft sits in the review queue)"
                  }
                },
                "required": [
                  "feedback"
                ]
              }
            }
          }
        }
      }
    },
    "/messages/{id}/mark-sent": {
      "post": {
        "tags": [
          "messages"
        ],
        "summary": "mark a pending manual-channel draft as sent outside the platform. manual channels are the ones the API cannot deliver on: every tiktok draft, and instagram cold first-touch. completes the draft - review - done lifecycle for manual DMs",
        "operationId": "markMessageSent",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/MarkMessageSentResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "SERVER_002: draft is API-sendable or channel not manual",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "SERVER_003: no pending draft or approval item with that id",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "approval queue item id, or the message id - drafts created through POST /conversations/:id/messages have no approval item, so their message id is the handle (2.18.0)",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "description": "api-sendable drafts (email, twitter, instagram follow-ups with a connected account) must go through /approve instead - a recorded 'sent' always means a real transmission\n\ninstagram cold first-touch additionally requires a connected instagram account (replies arrive via webhook); tiktok does not (record replies via POST /conversations/:id/messages)\n\na draft with no approval item gets a terminal 'sent' item recorded when its campaign contact resolves; approval_id is null when it cannot be"
      }
    },
    "/messages/bulk": {
      "post": {
        "tags": [
          "messages"
        ],
        "summary": "bulk approve or reject messages",
        "operationId": "bulkMessageAction",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/BulkMessageActionResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "affected_count": 5,
                    "contact_ids": [
                      "uuid",
                      "uuid"
                    ],
                    "skipped_count": 0,
                    "status": "approved"
                  }
                }
              }
            }
          }
        },
        "x-scope": "send",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "approve",
                      "reject"
                    ],
                    "description": "action to perform"
                  },
                  "message_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "message queue item IDs (1-100)"
                  },
                  "reason": {
                    "type": "string",
                    "description": "rejection reason (only used when action is reject)"
                  }
                },
                "required": [
                  "action",
                  "message_ids"
                ]
              }
            }
          }
        },
        "description": "approve returns affected_count, contact_ids, skipped_count, and status; reject returns affected_count and contact_ids only."
      }
    },
    "/ai/generate": {
      "post": {
        "tags": [
          "AI"
        ],
        "summary": "generate AI content (email subject + body)",
        "operationId": "generateAiContent",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AiGenerateResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "AI_004: AI rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "AI_002: AI generation failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "generate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "generation_type": {
                    "type": "string",
                    "description": "type of content to generate (e.g. initial_outreach, follow_up, reply)"
                  },
                  "tone": {
                    "type": "string",
                    "description": "tone for the generated content (e.g. professional, casual, warm-direct)"
                  },
                  "campaign_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "campaign to scope the generation to"
                  },
                  "contact_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "target contact ID"
                  },
                  "prompt": {
                    "type": "string",
                    "description": "additional freeform instructions for the generation"
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "email",
                      "dm"
                    ],
                    "description": "output format. 'dm' produces short platform-native message text with an empty subject - no greeting, no signature. defaults to email",
                    "default": "email"
                  },
                  "input_context": {
                    "type": "object",
                    "description": "structured context, e.g. { include_cta: boolean }"
                  }
                },
                "required": [
                  "generation_type",
                  "tone"
                ]
              }
            }
          }
        },
        "description": "requires an API key with `generate` scope. agents do not call this directly. drafting runs as an internal QStash worker inside POST /campaigns.\n\nwhen contact_id is set, the contact's tags and enrichment_data are fed into the generation context automatically - store per-contact intel there instead of smuggling it through prompt\n\nthe draft states nothing the context doesn't support: it is grounded in the account's saved outreach background plus the campaign's goal/product fields, and never invents a company, location, or customer win. with no sender context on the campaign at all, the draft stays general and confidence_score is capped at 0.4"
      }
    },
    "/ai/generate/campaign": {
      "post": {
        "tags": [
          "AI"
        ],
        "summary": "generate campaign-level outreach content (email sequence, templates) from an inline brief. content-first: pass the strategy directly, no campaign id required",
        "operationId": "generateCampaignContent",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AiGenerateCampaignResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "422": {
            "description": "SERVER_005: missing or invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "AI_004: AI rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "generate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "campaign_name": {
                    "type": "string",
                    "description": "campaign name (used as the brief title)"
                  },
                  "objective": {
                    "type": "string",
                    "description": "campaign objective (e.g. \"book DJ gigs\", \"sell SaaS to VPs of Eng\")"
                  },
                  "target_audience": {
                    "type": "string",
                    "description": "target audience description"
                  },
                  "key_benefits": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "non-empty list of key benefits to emphasise"
                  },
                  "tone": {
                    "type": "string",
                    "description": "tone (e.g. professional, casual, warm-direct)"
                  }
                },
                "required": [
                  "campaign_name",
                  "objective",
                  "target_audience",
                  "key_benefits",
                  "tone"
                ]
              }
            }
          }
        }
      }
    },
    "/ai/analyze": {
      "post": {
        "tags": [
          "AI"
        ],
        "summary": "analyze an inbound message (email or DM) for intent, sentiment, key points, and a suggested reply",
        "operationId": "analyzeResponse",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AiAnalyzeResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "intent_type": "interested",
                    "sentiment": "positive",
                    "key_points": [
                      "asked about pricing for 50 seats",
                      "wants demo next week"
                    ],
                    "suggested_response": "Hi {{first_name}}, ...",
                    "requires_human_review": false,
                    "extracted_data": {
                      "seats": 50,
                      "timing": "next week"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "AI_004: AI rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "generate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "conversation_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "conversation ID: the analysis is scoped to this thread's history and contact"
                  },
                  "message_content": {
                    "type": "string",
                    "description": "inbound message text to analyze. `email_content` is accepted as a legacy alias."
                  }
                },
                "required": [
                  "conversation_id",
                  "message_content"
                ]
              }
            }
          }
        },
        "description": "requires an API key with `generate` scope. agents do not call this directly. response analysis runs as an internal step of the campaign workflow when an inbound reply arrives."
      }
    },
    "/ai/usage": {
      "get": {
        "tags": [
          "AI"
        ],
        "summary": "get AI generation counts for the current billing period, broken down by generation_type. iris does not enforce a separate AI quota - generations are bounded implicitly by the campaign envelope, so no limit field is exposed.",
        "operationId": "getAiUsage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AiUsage"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "billing_period_start": "2026-04-30T01:00:04.245Z",
                    "billing_period_end": "2026-05-30T01:00:04.245Z",
                    "total_generations": 14,
                    "total_tokens": 11680,
                    "by_generation_type": {
                      "draft_email": 8,
                      "draft_dm": 4,
                      "suggested_response": 2
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read"
      }
    },
    "/discovery/search": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "start an asynchronous contact discovery search across configured sources (Instagram, TikTok, and public business listings). returns a job_id - poll GET /discovery/jobs/:id for results",
        "operationId": "searchDiscovery",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/DiscoveryJobHandle"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "job_id": "uuid"
                  }
                }
              }
            }
          },
          "429": {
            "description": "DISCOVERY_008: discovery quota exceeded; DISCOVERY_006: discovery rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "generate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "keywords": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "non-empty array of keywords to search for (e.g. ['coffee shop', 'cafe'])"
                  },
                  "location": {
                    "type": "string",
                    "description": "location to search around (city, address, lat/lng string)"
                  },
                  "radius_miles": {
                    "type": "number",
                    "description": "search radius in miles",
                    "default": 25
                  },
                  "max_results": {
                    "type": "integer",
                    "description": "maximum results to return (10-500)",
                    "default": 50
                  },
                  "sources": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "discovery sources to use (e.g. ['instagram', 'tiktok']). defaults to all available sources"
                  },
                  "campaign_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "campaign to associate discovered contacts with"
                  },
                  "profile_type": {
                    "type": "string",
                    "enum": [
                      "local_business",
                      "content_creator",
                      "influencer",
                      "b2b_professional",
                      "ecommerce",
                      "saas_company",
                      "agency",
                      "freelancer",
                      "other"
                    ],
                    "description": "target profile type, used to route the appropriate discovery source"
                  },
                  "enrich_emails": {
                    "type": "boolean",
                    "description": "attempt to enrich discovered contacts with email addresses",
                    "default": true
                  }
                },
                "required": [
                  "keywords"
                ]
              }
            }
          }
        },
        "description": "discovery is asynchronous - the response returns a job_id only. poll GET /discovery/jobs/:id until status is 'completed' to retrieve the discovered contacts.\n\nto fan out a discovery run by campaign target profile, use POST /discovery/search/campaign (also async - poll GET /discovery/jobs/:id).\n\nrequires an API key with `generate` scope. agents do not call this directly. discovery runs as an internal step of POST /campaigns."
      }
    },
    "/discovery/search/campaign": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "run discovery search using campaign target profiles",
        "operationId": "searchCampaignDiscovery",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/DiscoveryJobHandle"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "job_id": "uuid"
                  }
                }
              }
            }
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "DISCOVERY_008: discovery quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "generate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "campaign_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "campaign ID"
                  },
                  "selected_profile_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "specific target profile IDs to use (defaults to all profiles on the campaign)"
                  },
                  "additional_keywords": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "extra keywords to append to each profile's discovery query"
                  },
                  "max_results": {
                    "type": "integer",
                    "description": "maximum results to return (10-500)",
                    "default": 50
                  },
                  "sources": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "discovery sources to use (e.g. ['instagram', 'tiktok']). defaults to all available sources"
                  }
                },
                "required": [
                  "campaign_id"
                ]
              }
            }
          }
        },
        "description": "discovery is asynchronous - the response returns a job_id only. poll GET /discovery/jobs/:id until status is 'completed'."
      }
    },
    "/discovery/jobs/{id}": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "get the status of a discovery job",
        "operationId": "getDiscoveryJob",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/DiscoveryJob"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "status": "completed",
                    "progress_percent": 100,
                    "progress_message": "discovery complete",
                    "error": null,
                    "started_at": "2024-01-15T10:30:00Z",
                    "completed_at": "2024-01-15T10:35:00Z",
                    "created_at": "2024-01-15T10:30:00Z",
                    "updated_at": "2024-01-15T10:35:00Z",
                    "contact_count": 42,
                    "contacts": []
                  }
                }
              }
            }
          },
          "404": {
            "description": "DISCOVERY_002: discovery job not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/discovery/sources": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "list available discovery data sources",
        "operationId": "listDiscoverySources",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DiscoverySource"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "instagram",
                      "name": "Instagram",
                      "available": true
                    },
                    {
                      "id": "tiktok",
                      "name": "TikTok",
                      "available": true
                    }
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read"
      }
    },
    "/analytics/overview": {
      "get": {
        "tags": [
          "analytics"
        ],
        "summary": "get overall analytics overview across all campaigns",
        "operationId": "getAnalyticsOverview",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AnalyticsOverview"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "campaigns": {
                      "total": 12,
                      "by_status": {
                        "draft": 4,
                        "active": 3,
                        "completed": 5
                      }
                    },
                    "contacts": {
                      "total": 1250
                    },
                    "conversations": {
                      "total": 450,
                      "by_status": {
                        "active": 120,
                        "closed": 330
                      }
                    },
                    "messages": {
                      "total": 230,
                      "by_status": {
                        "approved": 200,
                        "pending_approval": 30
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "description": "by_status keys are dynamic. they reflect whatever statuses exist in the user's data. Common values: campaigns (draft, active, paused, completed); conversations (active, archived, closed); messages (pending_approval, approved, rejected, sent, failed)."
      }
    },
    "/analytics/campaigns/{id}": {
      "get": {
        "tags": [
          "analytics"
        ],
        "summary": "get analytics for a specific campaign",
        "operationId": "getCampaignAnalytics",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/CampaignAnalytics"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "campaign": {
                      "id": "uuid",
                      "name": "Q1 outreach",
                      "status": "active",
                      "created_at": "2024-01-15T10:30:00Z",
                      "updated_at": "2024-01-16T08:00:00Z"
                    },
                    "contacts": {
                      "total": 150,
                      "by_status": {
                        "active": 120,
                        "opted_out": 30
                      }
                    },
                    "conversations": {
                      "total": 42,
                      "by_status": {
                        "active": 12,
                        "closed": 30
                      }
                    },
                    "messages": {
                      "total": 230,
                      "by_status": {
                        "sent": 200,
                        "pending_approval": 30
                      }
                    },
                    "delivery_status": {
                      "sent": 42,
                      "delivered": 40,
                      "opened": 28,
                      "clicked": 12
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "CAMP_001: campaign not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/analytics/performance": {
      "get": {
        "tags": [
          "analytics"
        ],
        "summary": "get performance metrics over time",
        "operationId": "getPerformanceMetrics",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/PerformanceMetrics"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "number of days to include in the time series (1-90)",
            "schema": {
              "type": "integer",
              "default": 30
            }
          },
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "filter to a single campaign",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/analytics/response-time": {
      "get": {
        "tags": [
          "analytics"
        ],
        "summary": "get average response time metrics",
        "operationId": "getResponseTimeMetrics",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ResponseTimeMetrics"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "filter by campaign",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/analytics/contact-types": {
      "get": {
        "tags": [
          "analytics"
        ],
        "summary": "get contact type distribution",
        "operationId": "getContactTypeDistribution",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ContactTypeDistribution"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "filter to a single campaign",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/usage": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "get your current plan, quota usage, and billing period in one call - the campaign envelope (campaigns per period with used/remaining) plus the per-campaign contact and message limits. `\"unlimited\"` replaces numeric limits on team plans.",
        "operationId": "getUsage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/UsageData"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "plan": "starter",
                    "is_locked": false,
                    "is_team": false,
                    "billing_period": {
                      "start": "2026-07-01T00:00:00.000Z",
                      "end": "2026-07-31T23:59:59.999Z"
                    },
                    "limits": {
                      "campaigns_per_period": {
                        "limit": 5,
                        "used": 2,
                        "remaining": 3
                      },
                      "contacts_per_campaign": {
                        "limit": 30
                      },
                      "messages_per_campaign": {
                        "limit": 240
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read"
      }
    },
    "/billing/plans": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "get available billing plans and their features",
        "operationId": "listPlans",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BillingPlan"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "uuid",
                      "plan_name": "free",
                      "display_name": "Free",
                      "description": "get started at no cost",
                      "monthly_price_cents": 0,
                      "yearly_price_cents": 0,
                      "campaigns_per_period": 1,
                      "contacts_per_campaign": 30,
                      "messages_per_campaign": 240,
                      "is_active": true,
                      "sort_order": 0,
                      "created_at": "2024-01-01T00:00:00Z",
                      "updated_at": "2024-01-01T00:00:00Z"
                    },
                    {
                      "id": "uuid",
                      "plan_name": "starter",
                      "display_name": "Starter",
                      "description": "for growing outreach",
                      "monthly_price_cents": 1200,
                      "yearly_price_cents": 12000,
                      "campaigns_per_period": 5,
                      "contacts_per_campaign": 30,
                      "messages_per_campaign": 240,
                      "is_active": true,
                      "sort_order": 1,
                      "created_at": "2024-01-01T00:00:00Z",
                      "updated_at": "2024-01-01T00:00:00Z"
                    }
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read"
      }
    },
    "/autopilot": {
      "get": {
        "tags": [
          "autopilot"
        ],
        "summary": "get autopilot status: whether it's configured, the current config, the pending-review count for the standing campaign, and the latest run's step results",
        "operationId": "getAutopilot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AutopilotStatus"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "configured": true,
                    "config": {
                      "enabled": true,
                      "campaign_id": "uuid",
                      "max_new_contacts_per_run": 10,
                      "max_pending_reviews": 25,
                      "run_hour": 2,
                      "timezone": "America/New_York",
                      "paused": false,
                      "pause_reason": null,
                      "created_at": "2026-07-01T00:00:00Z",
                      "updated_at": "2026-07-09T02:00:00Z"
                    },
                    "pending_reviews": 4,
                    "last_run": {
                      "run_date": "2026-07-09",
                      "steps": [
                        {
                          "step": "refresh_insights",
                          "status": "completed"
                        },
                        {
                          "step": "discover_contacts",
                          "status": "completed"
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "read"
      },
      "patch": {
        "tags": [
          "autopilot"
        ],
        "summary": "create or update the autopilot config. merge semantics: only the fields you send change; the first call creates the config with defaults for anything omitted. autopilot never sends - every drafted message waits in your approval queue.",
        "operationId": "updateAutopilot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AutopilotConfig"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "enabled": true,
                    "campaign_id": "uuid",
                    "max_new_contacts_per_run": 15,
                    "max_pending_reviews": 25,
                    "run_hour": 2,
                    "timezone": "America/New_York",
                    "paused": false,
                    "pause_reason": null,
                    "created_at": "2026-07-01T00:00:00Z",
                    "updated_at": "2026-07-09T14:30:00Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "SERVER_002: invalid timezone, or enabled without a campaign_id",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "BILLING_003: autopilot needs an active subscription",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "turn the nightly loop on or off. enabling requires a campaign_id and clears any pause state"
                  },
                  "campaign_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "the ONE standing campaign autopilot tends (must be yours and draft, scheduled, or active). null to unset"
                  },
                  "max_new_contacts_per_run": {
                    "type": "integer",
                    "minimum": 10,
                    "maximum": 50,
                    "description": "discovery batch size per nightly run",
                    "default": 10
                  },
                  "max_pending_reviews": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 200,
                    "description": "skip discovery while this many drafts sit unreviewed in the approval queue",
                    "default": 25
                  },
                  "run_hour": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 23,
                    "description": "local hour the nightly run fires",
                    "default": 2
                  },
                  "timezone": {
                    "type": "string",
                    "description": "IANA timezone for run_hour (e.g. America/New_York)",
                    "default": "America/New_York"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/autopilot/run": {
      "post": {
        "tags": [
          "autopilot"
        ],
        "summary": "queue a manual autopilot run immediately. steps that already completed today are skipped, so this tops up the approval queue rather than double-discovering. rate limited to 2 per hour.",
        "operationId": "triggerAutopilotRun",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "202": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/AutopilotRunQueued"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "queued": true,
                    "run_date": "2026-07-09"
                  }
                }
              }
            }
          },
          "400": {
            "description": "SERVER_002: autopilot is disabled or paused",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "BILLING_003: autopilot needs an active subscription",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "SERVER_003: autopilot is not set up yet",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "RATE_001: manual run rate limit exceeded (2 per hour)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "generate"
      }
    },
    "/channels/accounts": {
      "get": {
        "tags": [
          "channels"
        ],
        "summary": "list connected social accounts",
        "operationId": "listConnectedAccounts",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ConnectedAccount"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "uuid",
                      "channel": "twitter",
                      "platform_username": "@myaccount",
                      "status": "active",
                      "created_at": "2024-01-15T10:30:00Z",
                      "updated_at": "2024-01-15T10:30:00Z"
                    }
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read"
      }
    },
    "/channels/availability": {
      "get": {
        "tags": [
          "channels"
        ],
        "summary": "per-channel availability with send mode: mode 'api' = deliverable via /channels/send when connected; mode 'manual' = tiktok's draft + mark-sent flow (no send API exists, never 'connected')",
        "operationId": "getChannelAvailability",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ChannelAvailability"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "channel": "email",
                      "available": true,
                      "connected": true
                    },
                    {
                      "channel": "twitter",
                      "available": true,
                      "connected": true
                    },
                    {
                      "channel": "instagram",
                      "available": true,
                      "connected": false
                    }
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read"
      }
    },
    "/channels/send": {
      "post": {
        "tags": [
          "channels"
        ],
        "summary": "send a message through a specific channel into an existing conversation",
        "operationId": "sendChannelMessage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/SendChannelMessageResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "CONVERSATION_001: conversation not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "MESSAGE_015: message limit reached",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "send",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "twitter",
                      "instagram"
                    ],
                    "description": "outreach channel"
                  },
                  "conversation_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID of an existing conversation to send the message into"
                  },
                  "recipient_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID of the contact who will receive the message"
                  },
                  "content": {
                    "type": "string",
                    "description": "message content (whitespace is trimmed)"
                  },
                  "subject": {
                    "type": "string",
                    "description": "subject line (email only - ignored for DM channels)"
                  },
                  "variables": {
                    "type": "string",
                    "description": "key/value pairs substituted into the content template (e.g. {{first_name}})"
                  }
                },
                "required": [
                  "channel",
                  "conversation_id",
                  "recipient_id",
                  "content"
                ]
              }
            }
          }
        },
        "description": "tiktok cannot be sent through this endpoint (no send API exists) - draft via campaigns or record via POST /conversations/:id/messages, and complete drafts with POST /messages/:id/mark-sent\n\nprerequisites: the conversation must already exist - there is no API endpoint to create one ad hoc. conversations are created by the campaign-activation flow when contacts are added to an active campaign. for queued AI drafts use the message-approval flow (GET /messages/pending → POST /messages/:id/approve).\n\nprerequisites: twitter and instagram require an OAuth-connected account on the user. connect via the iris dashboard at /settings/channels - there is no API for connecting social accounts.\n\ncheck GET /channels/availability before sending to avoid silent failures on disconnected channels.\n\nrequires an API key with `send` scope. agents do not call this directly. message sends run as an internal step of POST /campaigns + the message approval flow."
      }
    },
    "/notifications": {
      "get": {
        "tags": [
          "notifications"
        ],
        "summary": "list notifications",
        "operationId": "listNotifications",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Notification"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                }
              }
            }
          }
        },
        "x-scope": "read",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "read",
            "in": "query",
            "required": false,
            "description": "filter by read state (true/false)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "filter by notification type",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/notifications/{id}": {
      "patch": {
        "tags": [
          "notifications"
        ],
        "summary": "update a notification (e.g. mark as read)",
        "operationId": "updateNotification",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Notification"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "NOTIFICATION_001: notification not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "read": {
                    "type": "boolean",
                    "description": "mark as read/unread"
                  }
                },
                "required": [
                  "read"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "notifications"
        ],
        "summary": "delete a notification",
        "operationId": "deleteNotification",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "no content"
          },
          "404": {
            "description": "NOTIFICATION_001: notification not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-scope": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/notifications/read-all": {
      "post": {
        "tags": [
          "notifications"
        ],
        "summary": "mark all notifications as read",
        "operationId": "markAllNotificationsRead",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/MarkAllNotificationsReadResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "updated_count": 12
                  }
                }
              }
            }
          }
        },
        "x-scope": "write"
      }
    },
    "/webhooks": {
      "get": {
        "tags": [
          "webhooks"
        ],
        "summary": "list all webhook endpoints",
        "operationId": "listWebhooks",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ]
      },
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "create a new webhook endpoint",
        "operationId": "createWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "user_id": "uuid",
                    "url": "https://example.com/webhooks/iris",
                    "events": [
                      "campaign.created",
                      "contact.created"
                    ],
                    "description": "production events",
                    "active": true,
                    "secret": "whsec_a3f5b9c2d8e1f4a7b6c9d2e5f8a1b4c7d0e3f6a9b2c5d8e1f4a7b0c3d6e9f2a5",
                    "created_at": "2024-01-15T10:30:00Z",
                    "updated_at": "2024-01-15T10:30:00Z"
                  }
                }
              }
            }
          },
          "409": {
            "description": "SERVER_016: a webhook is already registered for this URL. update or delete it before re-creating.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "webhook endpoint URL (HTTPS)"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "event types to subscribe to (e.g. [\"campaign.created\", \"contact.created\"]). use [\"*\"] for all events"
                  },
                  "description": {
                    "type": "string",
                    "description": "optional description"
                  }
                },
                "required": [
                  "url",
                  "events"
                ]
              }
            }
          }
        },
        "description": "the signing secret is only returned on creation - store it securely\n\nnew secrets are prefixed `whsec_`. legacy bare-hex secrets created before the prefix was introduced still verify normally. the HMAC is computed over the stored value as-is.\n\neach (user, url) pair is unique. a 409 means you already have a webhook at that url. PATCH /webhooks/:id to update it, or DELETE /webhooks/:id then re-create."
      }
    },
    "/webhooks/{id}": {
      "get": {
        "tags": [
          "webhooks"
        ],
        "summary": "get a specific webhook endpoint",
        "operationId": "getWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "WEBHOOK_001: webhook not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      },
      "patch": {
        "tags": [
          "webhooks"
        ],
        "summary": "update a webhook endpoint",
        "operationId": "updateWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "WEBHOOK_001: webhook not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "webhook endpoint URL (HTTPS)"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "event types"
                  },
                  "active": {
                    "type": "boolean",
                    "description": "enable/disable"
                  },
                  "description": {
                    "type": "string",
                    "description": "description (max 500 chars)"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "webhooks"
        ],
        "summary": "delete a webhook endpoint",
        "operationId": "deleteWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "no content"
          },
          "404": {
            "description": "WEBHOOK_001: webhook not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "send a test event to a webhook endpoint",
        "operationId": "testWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/TestWebhookResponse"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "success": true,
                    "delivery_id": "uuid",
                    "response_status": 200,
                    "response_body": "OK"
                  }
                }
              }
            }
          },
          "404": {
            "description": "WEBHOOK_001: webhook not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "webhooks"
        ],
        "summary": "list recent webhook deliveries",
        "operationId": "getWebhookDeliveries",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "page_size": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "total_pages": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "page_size",
                        "total",
                        "total_pages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "WEBHOOK_001: webhook not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "page number",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "items per page",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ]
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "rotate the signing secret for a webhook. the new secret is returned once and the old secret is invalidated immediately. update HMAC verification on the receiver side before the next delivery, otherwise signature checks will fail.",
        "operationId": "rotateWebhookSecret",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/RotateSecretResponse"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "uuid",
                    "secret": "whsec_b7c4d1e8f2a5c9d6e3f0a7b4c1d8e5f2a9b6c3d0e7f4a1b8c5d2e9f6a3b0c7d4"
                  }
                }
              }
            }
          },
          "404": {
            "description": "WEBHOOK_001: webhook not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id"
          }
        ]
      }
    },
    "/agent/credits": {
      "get": {
        "tags": [
          "agent credits"
        ],
        "summary": "check the agent's current credit balance",
        "operationId": "listCredits",
        "security": [
          {
            "apiKey": []
          },
          {
            "agentPaymentAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreditBalance"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "balance": 7,
                    "identity_id": "uuid"
                  }
                }
              }
            }
          },
          "402": {
            "description": "payment required: agent payment auth (x402 or MPP). campaign creation costs $2.25 via x402 (crypto) or 1 credit ($2.40 effective via MPP credit pack).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "PAYMENT_005"
                        },
                        "message": {
                          "type": "string",
                          "example": "insufficient credits: pay $2.25 USDC per campaign (x402) or buy a 5-credit pack for $12.00 (MPP)"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    },
                    "x402": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "integer",
                          "example": 2
                        },
                        "scheme": {
                          "type": "string",
                          "example": "exact"
                        },
                        "network": {
                          "type": "string",
                          "example": "eip155:8453"
                        },
                        "asset": {
                          "type": "string",
                          "example": "USDC"
                        },
                        "amount": {
                          "type": "string",
                          "example": "2.25"
                        },
                        "receiver": {
                          "type": "string"
                        },
                        "resource": {
                          "type": "string"
                        }
                      }
                    },
                    "mpp": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "integer",
                          "example": 1
                        },
                        "method": {
                          "type": "string",
                          "example": "stripe"
                        },
                        "intent": {
                          "type": "string",
                          "example": "charge"
                        },
                        "currency": {
                          "type": "string",
                          "example": "usd"
                        },
                        "amount_cents": {
                          "type": "integer",
                          "example": 1200
                        },
                        "resource": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "description": "requires x402 or MPP identity header (no payment needed for balance check).\n\nreturns null balance for API key users (they don't use credits).",
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "API key (Bearer is_live_...) or x402 payment header (PAYMENT-SIGNATURE/X-PAYMENT, base64 challenge response).",
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "post": {
        "tags": [
          "agent credits"
        ],
        "summary": "purchase 5 credits with x402 or MPP payment",
        "operationId": "createCredit",
        "security": [
          {
            "apiKey": []
          },
          {
            "agentPaymentAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreditPurchaseResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "balance": 5,
                    "credits_added": 5,
                    "pack": "pack_5"
                  }
                }
              }
            }
          },
          "402": {
            "description": "payment required: agent payment auth (x402 or MPP). campaign creation costs $2.25 via x402 (crypto) or 1 credit ($2.40 effective via MPP credit pack).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "PAYMENT_005"
                        },
                        "message": {
                          "type": "string",
                          "example": "insufficient credits: pay $2.25 USDC per campaign (x402) or buy a 5-credit pack for $12.00 (MPP)"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    },
                    "x402": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "integer",
                          "example": 2
                        },
                        "scheme": {
                          "type": "string",
                          "example": "exact"
                        },
                        "network": {
                          "type": "string",
                          "example": "eip155:8453"
                        },
                        "asset": {
                          "type": "string",
                          "example": "USDC"
                        },
                        "amount": {
                          "type": "string",
                          "example": "2.25"
                        },
                        "receiver": {
                          "type": "string"
                        },
                        "resource": {
                          "type": "string"
                        }
                      }
                    },
                    "mpp": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "integer",
                          "example": 1
                        },
                        "method": {
                          "type": "string",
                          "example": "stripe"
                        },
                        "intent": {
                          "type": "string",
                          "example": "charge"
                        },
                        "currency": {
                          "type": "string",
                          "example": "usd"
                        },
                        "amount_cents": {
                          "type": "integer",
                          "example": 1200
                        },
                        "resource": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "PAYMENT_007: purchase failed after payment (contact support)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "description": "credit packs: 5 credits for $12.00 (MPP only). x402 agents pay per-campaign ($2.25) at POST /campaigns.\n\nx402 agents can pay per-campaign ($2.25) by replaying POST /campaigns with a PAYMENT-SIGNATURE header (x402 v2). MPP agents must use packs.\n\ncredits never expire. send PAYMENT-SIGNATURE (x402 v2) or Authorization: Payment (MPP) header.",
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "API key (Bearer is_live_...) or x402 payment header (PAYMENT-SIGNATURE/X-PAYMENT, base64 challenge response).",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/changelog": {
      "get": {
        "tags": [
          "changelog"
        ],
        "summary": "release history newest-first: version, date, type (feature/fix/breaking/docs), summary, and migration notes on breaking entries. public - the one-line X-Notice header on every response is the latest entry's summary; this is the structured history behind it",
        "operationId": "getChangelog",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ChangelogEntry"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "version": "1.0.0",
                      "date": "2026-07-21",
                      "type": "feature",
                      "summary": "..."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key starting with is_live_. Create at https://www.iris-ai.dev/settings under API keys."
      },
      "agentPaymentAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-PAYMENT",
        "description": "agent payment auth. supports x402 (X-PAYMENT or PAYMENT-SIGNATURE header with base64-encoded payment proof) and MPP (Authorization: Payment header with Stripe credential). POST /campaigns costs $2.25 USDC via x402 or 1 credit ($2.40 effective via MPP credit pack at POST /agent/credits). see https://www.x402.org for x402 details."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": false
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "example": "SERVER_001"
              },
              "message": {
                "type": "string",
                "example": "internal server error"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        }
      },
      "CountByStatus": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "by_status": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          }
        },
        "required": [
          "total",
          "by_status"
        ]
      },
      "UsageLimitEntry": {
        "type": "object",
        "properties": {
          "limit": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "string",
                "const": "unlimited"
              }
            ]
          },
          "used": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "remaining": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "string",
                "const": "unlimited"
              }
            ]
          }
        },
        "required": [
          "limit",
          "used",
          "remaining"
        ]
      },
      "UsageLimitOnly": {
        "type": "object",
        "properties": {
          "limit": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "string",
                "const": "unlimited"
              }
            ]
          }
        },
        "required": [
          "limit"
        ]
      },
      "ChangelogEntry": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string"
          },
          "date": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "feature",
              "fix",
              "breaking",
              "docs"
            ]
          },
          "summary": {
            "type": "string"
          },
          "migration": {
            "type": "string"
          }
        },
        "required": [
          "version",
          "date",
          "type",
          "summary"
        ]
      },
      "Campaign": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "objective_type": {
            "type": "string"
          },
          "product_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "product_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "product_description": {
            "type": [
              "string",
              "null"
            ]
          },
          "follow_up_enabled": {
            "type": "boolean"
          },
          "follow_up_max_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "follow_up_delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "venue_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "outreach_channels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "radius_miles": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "min_budget": {
            "type": [
              "number",
              "null"
            ]
          },
          "max_budget": {
            "type": [
              "number",
              "null"
            ]
          },
          "dynamic_fields": {},
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "user_id",
          "name",
          "status",
          "objective_type",
          "product_name",
          "product_url",
          "product_description",
          "follow_up_enabled",
          "follow_up_max_count",
          "follow_up_delay_days",
          "keywords",
          "venue_types",
          "outreach_channels",
          "location",
          "radius_miles",
          "min_budget",
          "max_budget",
          "dynamic_fields",
          "created_at",
          "updated_at"
        ]
      },
      "TargetProfile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "campaign_id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "profile_type": {
            "type": "string"
          },
          "fit_score": {
            "type": [
              "number",
              "null"
            ]
          },
          "job_titles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "industries": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "pain_points": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "buying_signals": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "discovery_keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "recommended_channels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "campaign_id",
          "name",
          "profile_type",
          "fit_score",
          "job_titles",
          "industries",
          "pain_points",
          "buying_signals",
          "discovery_keywords",
          "recommended_channels",
          "created_at",
          "updated_at"
        ]
      },
      "AudienceProfile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_type": {
            "type": "string"
          },
          "fit_score": {
            "type": [
              "number",
              "null"
            ]
          },
          "job_titles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "industries": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "company_sizes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "pain_points": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "buying_signals": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "discovery_sources": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "discovery_keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "outreach_angle": {
            "type": [
              "string",
              "null"
            ]
          },
          "contacts_discovered": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "profile_type",
          "fit_score",
          "job_titles",
          "industries",
          "company_sizes",
          "pain_points",
          "buying_signals",
          "discovery_sources",
          "discovery_keywords",
          "outreach_angle",
          "contacts_discovered",
          "created_at",
          "updated_at"
        ]
      },
      "CampaignUsage": {
        "type": "object",
        "properties": {
          "campaign_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "total_contacts": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "total_conversations": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "delivery_status": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          }
        },
        "required": [
          "campaign_id",
          "status",
          "total_contacts",
          "total_conversations",
          "delivery_status"
        ]
      },
      "CampaignContact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "first_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "company_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "job_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "website": {
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enrichment_data": {},
          "instagram_handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "twitter_handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "tiktok_handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "campaign_contact_id": {
            "type": "string"
          },
          "campaign_contact_status": {
            "type": "string"
          },
          "added_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "user_id",
          "email",
          "first_name",
          "last_name",
          "company_name",
          "job_title",
          "phone",
          "website",
          "tags",
          "enrichment_data",
          "created_at",
          "updated_at",
          "deleted_at",
          "campaign_contact_id",
          "campaign_contact_status",
          "added_at"
        ]
      },
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "first_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "company_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "job_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "website": {
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enrichment_data": {},
          "instagram_handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "twitter_handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "tiktok_handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "user_id",
          "email",
          "first_name",
          "last_name",
          "company_name",
          "job_title",
          "phone",
          "website",
          "tags",
          "enrichment_data",
          "created_at",
          "updated_at",
          "deleted_at"
        ]
      },
      "ContactUsage": {
        "type": "object",
        "properties": {
          "total_contacts": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "period_contacts": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "period_limit": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "period_start": {
            "type": "string"
          },
          "period_end": {
            "type": "string"
          }
        },
        "required": [
          "total_contacts",
          "period_contacts",
          "period_limit",
          "period_start",
          "period_end"
        ]
      },
      "BulkContactImportResult": {
        "type": "object",
        "properties": {
          "created": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "updated": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "failed": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "contacts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "user_id": {
                  "type": "string"
                },
                "email": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "first_name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "last_name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "company_name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "job_title": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "phone": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "website": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "tags": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "enrichment_data": {},
                "instagram_handle": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "twitter_handle": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "tiktok_handle": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "created_at": {
                  "type": "string"
                },
                "updated_at": {
                  "type": "string"
                },
                "deleted_at": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "id",
                "user_id",
                "email",
                "first_name",
                "last_name",
                "company_name",
                "job_title",
                "phone",
                "website",
                "tags",
                "enrichment_data",
                "created_at",
                "updated_at",
                "deleted_at"
              ]
            }
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "email": {
                  "type": "string"
                },
                "error": {
                  "type": "string"
                }
              },
              "required": [
                "email",
                "error"
              ]
            }
          }
        },
        "required": [
          "created",
          "updated",
          "failed",
          "contacts",
          "errors"
        ]
      },
      "BulkContactDeleteResult": {
        "type": "object",
        "properties": {
          "deletedCount": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "affectedCampaignIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "totalArchivedConversations": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "deletedCount",
          "affectedCampaignIds",
          "totalArchivedConversations"
        ]
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "campaign_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "contact_id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "channel": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "metadata": {},
          "contacts": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "full_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "company_name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "full_name",
              "email",
              "company_name"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "campaign_id",
          "contact_id",
          "user_id",
          "channel",
          "status",
          "metadata",
          "created_at",
          "updated_at"
        ]
      },
      "ConversationDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "campaign_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "contact_id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "channel": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "metadata": {},
          "contacts": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "full_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "company_name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "full_name",
              "email",
              "company_name"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "conversation_id": {
                  "type": "string"
                },
                "direction": {
                  "type": "string"
                },
                "channel": {
                  "type": "string"
                },
                "content": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "metadata": {},
                "created_at": {
                  "type": "string"
                },
                "updated_at": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "conversation_id",
                "direction",
                "channel",
                "content",
                "status",
                "metadata",
                "created_at",
                "updated_at"
              ]
            }
          }
        },
        "required": [
          "id",
          "campaign_id",
          "contact_id",
          "user_id",
          "channel",
          "status",
          "metadata",
          "created_at",
          "updated_at"
        ]
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "conversation_id": {
            "type": "string"
          },
          "direction": {
            "type": "string"
          },
          "channel": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "metadata": {},
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "conversation_id",
          "direction",
          "channel",
          "content",
          "status",
          "metadata",
          "created_at",
          "updated_at"
        ]
      },
      "EngagementMetrics": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "unread": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "by_status": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          },
          "by_channel": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          }
        },
        "required": [
          "total",
          "unread",
          "by_status",
          "by_channel"
        ]
      },
      "MarkConversationReadResult": {
        "type": "object",
        "properties": {
          "unread_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "contact_id": {
            "type": "string"
          },
          "already_read": {
            "type": "boolean"
          }
        },
        "required": [
          "unread_count",
          "contact_id",
          "already_read"
        ]
      },
      "CreateMessageResult": {
        "type": "object",
        "properties": {
          "message": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "conversation_id": {
                "type": "string"
              },
              "direction": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "subject": {
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "from_email": {
                "type": "string"
              },
              "to_email": {
                "type": "string"
              },
              "sent_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "created_at": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "conversation_id",
              "direction",
              "status",
              "subject",
              "body",
              "from_email",
              "to_email",
              "sent_at",
              "created_at"
            ]
          },
          "contact_id": {
            "type": "string"
          }
        },
        "required": [
          "message",
          "contact_id"
        ]
      },
      "PendingMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "campaign_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "conversation_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "channel": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "subject": {
            "type": [
              "string",
              "null"
            ]
          },
          "body": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "user_id",
          "campaign_id",
          "conversation_id",
          "channel",
          "status",
          "subject",
          "body",
          "created_at",
          "updated_at"
        ]
      },
      "ApproveMessageResult": {
        "type": "object",
        "properties": {
          "sent": {
            "type": "boolean"
          },
          "message_id": {
            "type": "string"
          },
          "channel": {
            "type": "string"
          },
          "contact_id": {
            "type": "string"
          }
        },
        "required": [
          "sent",
          "message_id",
          "channel"
        ]
      },
      "RejectMessageResult": {
        "type": "object",
        "properties": {
          "message_id": {
            "type": "string"
          },
          "contact_id": {
            "type": "string"
          }
        },
        "required": [
          "message_id"
        ]
      },
      "RetryMessageResult": {
        "type": "object",
        "properties": {
          "retried_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "contact_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "retried_count",
          "contact_ids"
        ]
      },
      "MessageFeedbackResult": {
        "type": "object",
        "properties": {
          "feedback_id": {
            "type": "string"
          },
          "revised_subject": {
            "type": "string"
          },
          "revised_body": {
            "type": "string"
          },
          "approval_queue_id": {
            "type": "string"
          },
          "message_id": {
            "type": "string"
          }
        },
        "required": [
          "feedback_id",
          "revised_subject",
          "revised_body"
        ]
      },
      "MarkMessageSentResult": {
        "type": "object",
        "properties": {
          "approval_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "message_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "conversation_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "contact_id": {
            "type": "string"
          }
        },
        "required": [
          "approval_id",
          "message_id",
          "conversation_id"
        ]
      },
      "BulkMessageActionResult": {
        "type": "object",
        "properties": {
          "affected_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "contact_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "skipped_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "status": {
            "type": "string"
          }
        },
        "required": [
          "affected_count",
          "contact_ids"
        ]
      },
      "AiUsage": {
        "type": "object",
        "properties": {
          "billing_period_start": {
            "type": "string"
          },
          "billing_period_end": {
            "type": "string"
          },
          "total_generations": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "total_tokens": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "by_generation_type": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          }
        },
        "required": [
          "billing_period_start",
          "billing_period_end",
          "total_generations",
          "total_tokens",
          "by_generation_type"
        ]
      },
      "AiGenerateResult": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "content": {
            "type": "string"
          }
        },
        "additionalProperties": {}
      },
      "AiGenerateCampaignResult": {
        "type": "object",
        "properties": {},
        "additionalProperties": {}
      },
      "AiAnalyzeResult": {
        "type": "object",
        "properties": {
          "intent_type": {
            "type": "string"
          },
          "sentiment": {
            "type": "string"
          },
          "key_points": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "suggested_response": {
            "type": "string"
          },
          "requires_human_review": {
            "type": "boolean"
          },
          "extracted_data": {}
        },
        "required": [
          "intent_type",
          "sentiment",
          "key_points",
          "suggested_response",
          "requires_human_review",
          "extracted_data"
        ]
      },
      "DiscoveryJobHandle": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string"
          }
        },
        "required": [
          "job_id"
        ]
      },
      "DiscoveryJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "progress_percent": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "progress_message": {
            "type": [
              "string",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "contact_count": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "contacts": {
            "type": [
              "array",
              "null"
            ],
            "items": {}
          }
        },
        "required": [
          "id",
          "status",
          "progress_percent",
          "progress_message",
          "error",
          "started_at",
          "completed_at",
          "created_at",
          "updated_at",
          "contact_count",
          "contacts"
        ]
      },
      "DiscoverySource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "available": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "available"
        ]
      },
      "AnalyticsOverview": {
        "type": "object",
        "properties": {
          "campaigns": {
            "$ref": "#/components/schemas/CountByStatus"
          },
          "contacts": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "total"
            ]
          },
          "conversations": {
            "$ref": "#/components/schemas/CountByStatus"
          },
          "messages": {
            "$ref": "#/components/schemas/CountByStatus"
          }
        },
        "required": [
          "campaigns",
          "contacts",
          "conversations",
          "messages"
        ]
      },
      "CampaignAnalytics": {
        "type": "object",
        "properties": {
          "campaign": {},
          "contacts": {
            "$ref": "#/components/schemas/CountByStatus"
          },
          "conversations": {
            "$ref": "#/components/schemas/CountByStatus"
          },
          "messages": {
            "$ref": "#/components/schemas/CountByStatus"
          },
          "delivery_status": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          }
        },
        "required": [
          "campaign",
          "contacts",
          "conversations",
          "messages",
          "delivery_status"
        ]
      },
      "PerformanceMetrics": {
        "type": "object",
        "properties": {
          "days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "time_series": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string"
                }
              },
              "required": [
                "date"
              ],
              "additionalProperties": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            }
          }
        },
        "required": [
          "days",
          "time_series"
        ]
      },
      "ResponseTimeMetrics": {
        "type": "object",
        "properties": {
          "total_conversations": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "conversations_with_replies": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "reply_rate": {
            "type": "number"
          },
          "average_response_time_ms": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "average_response_time_hours": {
            "type": "number"
          },
          "median_response_time_ms": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "median_response_time_hours": {
            "type": "number"
          }
        },
        "required": [
          "total_conversations",
          "conversations_with_replies",
          "reply_rate",
          "average_response_time_ms",
          "average_response_time_hours",
          "median_response_time_ms",
          "median_response_time_hours"
        ]
      },
      "ContactTypeDistribution": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "by_source": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          }
        },
        "required": [
          "total",
          "by_source"
        ]
      },
      "BillingPlan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "plan_name": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "monthly_price_cents": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "yearly_price_cents": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "campaigns_per_period": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "contacts_per_campaign": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "messages_per_campaign": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "is_active": {
            "type": "boolean"
          },
          "sort_order": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "plan_name",
          "display_name",
          "description",
          "monthly_price_cents",
          "yearly_price_cents",
          "campaigns_per_period",
          "contacts_per_campaign",
          "messages_per_campaign",
          "is_active",
          "sort_order",
          "created_at",
          "updated_at"
        ]
      },
      "ConnectedAccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "channel": {
            "type": "string"
          },
          "platform_username": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "channel",
          "platform_username",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "ChannelAvailability": {
        "type": "object",
        "properties": {
          "channel": {
            "type": "string"
          },
          "available": {
            "type": "boolean"
          },
          "connected": {
            "type": "boolean"
          },
          "mode": {
            "type": "string",
            "enum": [
              "api",
              "manual"
            ]
          }
        },
        "required": [
          "channel",
          "available",
          "connected",
          "mode"
        ]
      },
      "ContactHandle": {
        "type": "object",
        "properties": {
          "channel": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "profile_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_engageable": {
            "type": "boolean"
          },
          "follower_count": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "engagement_rate": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "channel",
          "handle",
          "profile_url",
          "is_engageable",
          "follower_count",
          "engagement_rate"
        ]
      },
      "SendChannelMessageResult": {
        "type": "object",
        "properties": {
          "deliveryResult": {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean"
              },
              "channel": {
                "type": "string"
              },
              "platformMessageId": {
                "type": "string"
              },
              "platformConversationId": {
                "type": "string"
              },
              "error": {
                "type": "string"
              },
              "errorCode": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              },
              "retryAfter": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "sentAt": {
                "type": "string"
              },
              "metadata": {}
            },
            "required": [
              "success",
              "channel"
            ],
            "additionalProperties": {}
          },
          "contactId": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "deliveryResult",
          "contactId"
        ]
      },
      "Notification": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "read": {
            "type": "boolean"
          },
          "metadata": {},
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "user_id",
          "type",
          "title",
          "message",
          "read",
          "metadata",
          "created_at"
        ]
      },
      "MarkAllNotificationsReadResult": {
        "type": "object",
        "properties": {
          "updated_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "updated_count"
        ]
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "key_prefix": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "user_id",
          "name",
          "key_prefix",
          "scopes",
          "last_used_at",
          "expires_at",
          "created_at"
        ]
      },
      "CreateApiKeyResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "key_prefix": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "key": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "user_id",
          "name",
          "key_prefix",
          "scopes",
          "last_used_at",
          "expires_at",
          "created_at",
          "key"
        ]
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "consecutive_failures": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "disabled_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "disabled_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "secret": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "user_id",
          "url",
          "events",
          "description",
          "active",
          "consecutive_failures",
          "disabled_at",
          "disabled_reason",
          "created_at",
          "updated_at"
        ]
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "webhook_id": {
            "type": "string"
          },
          "event_type": {
            "type": "string"
          },
          "payload": {},
          "response_status": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "response_body": {
            "type": [
              "string",
              "null"
            ]
          },
          "attempt_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "next_retry_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "failed_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "webhook_id",
          "event_type",
          "payload",
          "response_status",
          "response_body",
          "attempt_count",
          "next_retry_at",
          "delivered_at",
          "failed_at",
          "created_at"
        ]
      },
      "TestWebhookResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "delivery_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "response_body": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "success",
          "delivery_id",
          "response_status",
          "response_body"
        ]
      },
      "RotateSecretResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "secret": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "secret"
        ]
      },
      "CreditBalance": {
        "type": "object",
        "properties": {
          "balance": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "identity_id": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "balance"
        ]
      },
      "CreditPurchaseResult": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "credits_added": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "pack": {
            "type": "string"
          }
        },
        "required": [
          "balance",
          "credits_added",
          "pack"
        ]
      },
      "UsageData": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string"
          },
          "is_locked": {
            "type": "boolean"
          },
          "is_team": {
            "type": "boolean"
          },
          "billing_period": {
            "type": "object",
            "properties": {
              "start": {
                "type": "string"
              },
              "end": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "start",
              "end"
            ]
          },
          "limits": {
            "type": "object",
            "properties": {
              "campaigns_per_period": {
                "$ref": "#/components/schemas/UsageLimitEntry"
              },
              "contacts_per_campaign": {
                "$ref": "#/components/schemas/UsageLimitEntry"
              },
              "messages_per_campaign": {
                "$ref": "#/components/schemas/UsageLimitOnly"
              },
              "ai_generations_per_period": {
                "type": "object",
                "properties": {
                  "used": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "limit": {
                    "type": "string",
                    "const": "unlimited"
                  }
                },
                "required": [
                  "used",
                  "limit"
                ]
              }
            },
            "required": [
              "campaigns_per_period",
              "contacts_per_campaign",
              "messages_per_campaign",
              "ai_generations_per_period"
            ]
          }
        },
        "required": [
          "plan",
          "is_locked",
          "is_team",
          "billing_period",
          "limits"
        ]
      },
      "AutopilotConfig": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "campaign_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "max_new_contacts_per_run": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "max_pending_reviews": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "run_hour": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "timezone": {
            "type": "string"
          },
          "paused": {
            "type": "boolean"
          },
          "pause_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "enabled",
          "campaign_id",
          "max_new_contacts_per_run",
          "max_pending_reviews",
          "run_hour",
          "timezone",
          "paused",
          "pause_reason",
          "created_at",
          "updated_at"
        ]
      },
      "AutopilotStatus": {
        "type": "object",
        "properties": {
          "configured": {
            "type": "boolean"
          },
          "config": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "campaign_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "max_new_contacts_per_run": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "max_pending_reviews": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "run_hour": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "timezone": {
                "type": "string"
              },
              "paused": {
                "type": "boolean"
              },
              "pause_reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "created_at": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              }
            },
            "required": [
              "enabled",
              "campaign_id",
              "max_new_contacts_per_run",
              "max_pending_reviews",
              "run_hour",
              "timezone",
              "paused",
              "pause_reason",
              "created_at",
              "updated_at"
            ]
          },
          "pending_reviews": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "last_run": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "run_date": {
                "type": "string"
              },
              "steps": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "step": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "step",
                    "status"
                  ]
                }
              }
            },
            "required": [
              "run_date",
              "steps"
            ]
          }
        },
        "required": [
          "configured",
          "config",
          "pending_reviews",
          "last_run"
        ]
      },
      "AutopilotRunQueued": {
        "type": "object",
        "properties": {
          "queued": {
            "type": "boolean"
          },
          "run_date": {
            "type": "string"
          }
        },
        "required": [
          "queued",
          "run_date"
        ]
      }
    }
  }
}