openapi: 3.2.0 info: title: Plainrouter Meta Inventory Exposure API version: 0.5.0 description: 'Operations tagged MetaInventoryExposure across 2 of this provider''s published API definitions: dev-plainrouter-openapi.json, plainrouter-openapi.json. Each path carries the servers of the definition it was published in.' servers: - url: https://plainrouter.com/api/v1 description: Production security: - workspaceSecret: [] tags: - name: MetaInventoryExposure paths: /workspaces/{workspace}/admin/ad-accounts/{account_id}/inventory/metrics: get: operationId: get_inventory_metrics description: Compare daily Meta metrics with PlainRouter arrivals in the account timezone, within plan retention. Unknown object IDs are never exposed. summary: Compare Meta metrics with counted arrivals tags: - MetaInventoryExposure parameters: - name: workspace in: path required: true description: The workspace ID schema: type: integer - name: account_id in: path required: true schema: type: string - name: start_date in: query schema: type: - string - 'null' format: date - name: end_date in: query schema: type: - string - 'null' format: date - name: campaign_id in: query schema: type: - string - 'null' maxLength: 128 - name: adset_id in: query schema: type: - string - 'null' maxLength: 128 - name: ad_id in: query schema: type: - string - 'null' maxLength: 128 - name: include_changes in: query schema: type: boolean responses: '200': description: Account-local Meta metrics and counted arrivals, clamped to plan retention. content: application/json: schema: type: object properties: account: type: object properties: id: type: integer external_id: type: string name: type: - string - 'null' currency: type: - string - 'null' timezone: type: - string - 'null' status: type: string connection_status: type: - string - 'null' required: - id - external_id - name - currency - timezone - status - connection_status sync: type: object properties: campaigns_count: type: - integer - 'null' adsets_count: type: - integer - 'null' ads_count: type: - integer - 'null' counts_read_at: type: - string - 'null' required: - campaigns_count - adsets_count - ads_count - counts_read_at staleness: type: object properties: structure_synced_at: type: - string - 'null' metrics_synced_at: type: - string - 'null' last_error_code: type: - string - 'null' state: type: string required: - structure_synced_at - metrics_synced_at - last_error_code - state metrics: type: array items: type: object properties: id: type: integer platform_ad_account_id: type: integer ad_external_id: type: string campaign_external_id: type: - string - 'null' adset_external_id: type: - string - 'null' date: type: string account_currency: type: string spend: type: string impressions: type: integer clicks: type: integer inline_link_clicks: type: integer actions: anyOf: - type: object additionalProperties: {} - type: array items: {} - type: 'null' action_values: anyOf: - type: object additionalProperties: {} - type: array items: {} - type: 'null' fetched_at: type: - string - 'null' arrivals: type: - integer - 'null' creative_id: type: - string - 'null' generator: type: - string - 'null' generator_job: type: - string - 'null' parent_creative: type: - string - 'null' required: - id - platform_ad_account_id - ad_external_id - campaign_external_id - adset_external_id - date - account_currency - spend - impressions - clicks - inline_link_clicks - actions - action_values - fetched_at - arrivals - creative_id - generator - generator_job - parent_creative changes: type: array items: type: object properties: id: type: integer platform_ad_account_id: type: integer level: type: string external_id: type: string field: type: string old_value: type: - string - 'null' new_value: type: - string - 'null' observed_at: type: - string - 'null' required: - id - platform_ad_account_id - level - external_id - field - old_value - new_value - observed_at effective_range: type: - object - 'null' properties: from: type: string to: type: string required: - from - to object_metrics: type: array items: type: object properties: level: type: string enum: - campaign - adset - ad external_id: type: string date: type: string meta: type: - object - 'null' properties: account_currency: type: string spend: type: string impressions: type: integer clicks: type: integer inline_link_clicks: type: integer required: - account_currency - spend - impressions - clicks - inline_link_clicks arrivals: type: - integer - 'null' creative_id: type: - string - 'null' generator: type: - string - 'null' generator_job: type: - string - 'null' parent_creative: type: - string - 'null' required: - level - external_id - date - meta - arrivals unmatched_arrivals: type: - integer - 'null' required: - account - sync - staleness - metrics - changes - effective_range - object_metrics - unmatched_arrivals '401': description: Workspace read key missing or invalid. content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' '403': description: Workspace read grant required. content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' '404': description: Account not found or outside the key binding. content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' '422': description: Request validation failed. content: application/json: schema: $ref: '#/components/schemas/ValidationError' security: - workspaceInventoryKey: [] servers: - url: https://plainrouter.com/api/v1 description: Production /workspaces/{workspace}/admin/ad-accounts/{account_id}/inventory: get: operationId: get_account_inventory description: Read complete Meta objects with account-wide totals on every page. Continue with next_cursor as after_id; scope and filters stay unchanged. summary: Read account inventory tags: - MetaInventoryExposure parameters: - name: workspace in: path required: true description: The workspace ID schema: type: integer - name: account_id in: path required: true schema: type: string - name: level in: query schema: type: - string - 'null' enum: - campaign - adset - ad - null - name: effective_status in: query schema: type: - string - 'null' maxLength: 50 - name: campaign_id in: query schema: type: - string - 'null' maxLength: 128 - name: adset_id in: query schema: type: - string - 'null' maxLength: 128 - name: after_id in: query description: Continue using next_cursor with the same filters; rule lists use an immutable rule ID, other lists an offset or object ID. schema: type: integer minimum: 1 - name: limit in: query description: Maximum complete rows; the byte budget may return fewer. Defaults to 25. schema: type: integer default: 25 minimum: 1 maximum: 200 responses: '404': description: Workspace is nonexistent, inaccessible or noncanonical, or the account is not found or outside the key binding. content: application/json: schema: anyOf: - $ref: '#/components/schemas/ApiRouteNotFound' - type: object properties: message: type: string const: Account not found. required: - message '401': description: Invalid or missing Server secret. content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' '200': description: Bounded account inventory with summary totals. Result projections share the 80,000-byte MCP JSON budget; defaults are bounded, next_cursor continues complete rows, and oversized single rows are explicitly refused. Plan creative continuation uses the read endpoint; proposal continuation uses the batch read endpoint. content: application/json: schema: type: object description: Complete projection rows are paged within 80,000 JSON bytes, accounting for both MCP representations. Defaults are bounded. Follow next_cursor with the same scope and filters. One oversized row is explicitly refused; fields are never silently clipped. properties: account: type: object additionalProperties: {} sync: type: object additionalProperties: {} staleness: type: object additionalProperties: {} summary: type: object properties: total: type: integer by_level: type: object additionalProperties: type: integer objects: type: array items: type: object additionalProperties: {} next_cursor: type: - integer - 'null' truncated: type: boolean continuation: type: string required: - account - sync - staleness - summary - objects - next_cursor - truncated - continuation servers: - url: https://plainrouter.com/api/v1 description: Production components: schemas: ValidationError: type: object properties: message: type: string errors: type: object additionalProperties: type: array items: type: string required: - message - errors title: ValidationError ErrorMessage: type: object properties: message: type: string required: - message title: ErrorMessage ApiRouteNotFound: type: object properties: error: type: object properties: code: type: string enum: - api_route_not_found message: type: string resolution: type: string required: - code - message - resolution request: type: object properties: method: type: string path: type: string required: - method - path resources: type: object properties: documentation: type: string openapi: type: string required: - documentation - openapi required: - error - request - resources title: ApiRouteNotFound securitySchemes: workspaceSecret: type: http description: Per-workspace Server secret. It authenticates only the Signals workspace represented by the credential. scheme: bearer sandboxCredential: type: http description: Short-lived Sandbox key issued by POST /sandbox/keys. scheme: bearer workspaceActionKey: type: http description: Workspace key with read-actions for reads or propose-actions for writes. Unbound keys select an available advertising account with account_id. scheme: bearer planWriter: type: http description: An OAuth agent or account-bound Workspace Key with write access and the plan-create grant. scheme: bearer workspaceInventoryKey: type: http description: Workspace read key with the get_inventory_metrics grant. Account-bound keys can read only their bound account. scheme: bearer planReader: type: http description: An OAuth agent or account-bound Workspace Key with read access to the approved ad account. scheme: bearer creativeWriter: type: http description: Workspace-bound write credential with a grant authorizing creative intake. scheme: bearer testReader: type: http description: A workspace principal with read tier and the launch.plans.index and launch.plans.show grants for this account. scheme: bearer testWriter: type: http description: A workspace principal with write tier and the launch.plans.store grant for this account. scheme: bearer ruleReader: type: http description: 'A workspace-scoped key with read ability and actions.rules.index or actions.rules.show access to the bound account. Send Accept: application/json.' scheme: bearer ruleWriter: type: http description: 'A workspace-scoped key with write ability and the actions.rules.store or actions.rules.update grant. Send Accept: application/json.' scheme: bearer agentContextKey: type: http description: Workspace key with read ability, ad-account.read permission and the agent.context grant. scheme: bearer agentContextOAuth: type: oauth2 description: OAuth access token for an active approved agent principal with mcp:use, ad-account.read and agent.context authorization. Authorization code with PKCE and device authorization tokens are accepted. This scheme applies only to agent context. flows: authorizationCode: authorizationUrl: https://plainrouter.com/oauth2/authorize tokenUrl: https://plainrouter.com/oauth2/token refreshUrl: https://plainrouter.com/oauth2/token scopes: mcp:use: Use the approved agent principal. x-refined-from: - dev-plainrouter-openapi.json - plainrouter-openapi.json x-action-types: - increase_budget - decrease_budget - pause - resume - replace_creative - shift_spend - rollback - create_campaign - create_ad_set - create_ad - upload_asset x-signed: true