> ## Documentation Index
> Fetch the complete documentation index at: https://docs.narrative.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Simulate an NQL query against access rules

> Check which of a chosen set of access rules would deny a `SELECT` or `MERGE` statement, without running
it. Nothing is stored and no data is read: no job is created and no credits are charged.

The statement runs as the caller's company, in the role of a buyer, against the listed access rules
only. An entry is a stored access rule that the caller's company owns or can query, or an inline access
rule defined in the request. Each access rule moves, with the datasets it reads, to a placeholder company
named by its `placeholder_owner_slug`, and the statement reads it as
`<placeholder_owner_slug>.<access_rule_name>` or through `narrative.rosetta_stone`. The placeholder
company exists only for this request. Its slug can be the slug of a real company, such as the access
rule's real owner, and that company's data is never involved.

The statement reads the caller's own active datasets only through `company_data`: by id, by name, or all
of them through `company_data.rosetta_stone`. The caller's own slug is not a namespace in a simulation.
Views and derived mappings are not available, and opt-out datasets and dataset statistics are not loaded.
Query policies are evaluated before opt-out and sampling would apply, so neither changes which access
rules are denied. The policies are checked by the same query policy evaluation a normal query goes
through.

The response lists, per access rule and query table, the violations that denied it. A listed access rule
that is not in the list was not denied: its policy allowed the statement, or the statement did not read
it.

Requires a token with read access to subscriptions.



## OpenAPI

````yaml https://docs-cdn.narrative.io/api-reference/main/openapi.json post /v2/nql/simulate
openapi: 3.1.1
info:
  contact:
    email: support@narrative.io
    name: Narrative Support
    url: https://www.narrative.io
  termsOfService: https://www.narrative.io/legal/terms-of-service
  x-logo:
    url: >-
      https://cdn.narrative.io/images/company-logos/prod/narrative-logo-text-white.svg
    backgroundColor: rgb(9, 34, 166)
    altText: Narrative Logo
  description: >-
    The [Narrative Data Collaboration Platform](https://app.narrative.io) API is
    organized around REST. Our API has predictable resource-oriented URLs,
    accepts form-encoded request bodies, returns JSON-encoded responses, and
    uses standard HTTP response codes, authentication, and verbs.



    The current version is a pre-release beta.  It may result in unexpected
    behavior and there may be breaking changes in future releases up to the 1.0
    release.
  title: Narrative Data Collaboration Platform API
  version: 2.4.x
servers:
  - url: https://api-dev.narrative.io
  - url: https://api.narrative.io
security: []
tags:
  - name: Access Rules
    description: >-
      Access rules let data providers control who can purchase their data and
      the terms of purchase.


      The `access-rules` API allows you to manage access rules for your
      datasets.


      Related guides:
        - [What is an access rule?](https://kb.narrative.io/access-rules)
  - name: Agent Conversations
    description: >-
      Build LLM-driven workflows that can call MCP tools, ask the caller for
      input, and return structured answers.


      A conversation pins a model, a system prompt, and a tool catalog. Each run
      sends the model a user message (or

      a batch of tool outputs from a previously-paused run); the model decides
      whether to answer directly, call a

      server-side tool (resolved by the platform via Model Context Protocol), or
      call a client-side tool (which pauses

      the run with `requires_action` and waits for the caller to reply).


      Related guides:
        - [Agent Conversations Reference](https://docs.narrative.io/reference/architecture/agent-conversations)
        - [Error catalog](https://docs.narrative.io/reference/architecture/agent-conversations/errors/conversation-not-found)
  - name: MCP Connections
    description: >-
      Connect external (non-Narrative) MCP servers so agent runs can call their
      tools with the

      calling user's own OAuth authorization.


      A connection is created interactively: `POST /mcp-connections` runs OAuth
      discovery and

      Dynamic Client Registration against the server and returns a consent URL;
      the user authorizes

      in a browser; the authorization server redirects to `GET
      /mcp-connections/callback`, which

      stores the authorization code and sends the browser on to the Narrative
      app; the app calls

      `POST /mcp-connections/complete` with the user's own bearer token, which
      exchanges the code and

      marks the connection `connected`.


      That last step is authenticated on purpose. The callback is public — it's
      a cross-site browser

      redirect, so no bearer reaches it — so it is not allowed to complete
      anything. Only the user

      who started the flow can turn the stored code into a token.


      Tokens are stored encrypted and used server-side — they are never returned
      by the API. Once

      connected, reference the connection by id from an agent run's
      `mcp_servers[].connection_id`.
  - name: App Invites
    description: >-
      App invites allow applications to create one-time, shareable links on
      behalf of their users. These links

      enable users to invite third parties who do not have a Narrative account
      to perform actions within the

      application.


      For example, a Narrative user can send an invite link to a third party who
      then completes a Pinterest

      OAuth flow and creates a connector profile in the inviter's account,
      allowing the inviter to deliver

      audience data to the third party's Pinterest account without the third
      party needing a Narrative account.


      This API is intended to be used by applications (via app client
      credentials) to create and manage invites

      on behalf of their users, which can then be shared with invitees.
  - name: Apps
    description: >-
      Apps are applications bundled with a UI that can perform various actions
      on behalf of a user utilizing the Narrative API.

      Related guides:
        - [Building a Narrative Native App](https://www.narrative.io/knowledge-base/how-to-guides/building-a-narrative-native-app)
  - name: Access Tokens
    description: >-
      System Access Tokens are long-lived bearer credentials for calling the API
      without a user present.


      A token belongs to a company, carries an explicit list of permissions, and
      expires on a date you choose — at

      least a day out and at most a year. `admin` access cannot be granted to
      one.


      `POST /access-tokens/tokens` is the only endpoint that returns the
      credential. Everything after that works in

      terms of the token's id: the list, get and update responses describe a
      token without ever repeating its

      `access_token`. If you lose it, delete the token and create another.


      Related guides:
        - [How to Create an API Token](https://www.narrative.io/knowledge-base/how-to-guides/understanding-narratives-apis/create-an-api-token)
  - name: Attributes
    description: >-
      An attribute models a standardized data point available for sale on the
      Narrative marketplace.


      Narrative automatically turns data points from provider datasets into
      attributes so that buyers can purchase well-formed, standardized data from
      any supplier on the marketplace.
  - name: Auth
    description: >-
      API token is a crucial step for developers to securely authenticate
      requests to the Narrative API

      Related guides:
        - [How to Create an API Token](https://www.narrative.io/knowledge-base/how-to-guides/understanding-narratives-apis/create-an-api-token)
  - name: Authentication
    description: User login and registration
  - name: Billings
    description: Used by Narrative internally to bill customers
  - name: Companies
    description: A collection of employees
  - name: Company Marketing Information
    description: Useful information related to companies
  - name: Compute Pools
    description: >-
      Compute pools represent compute resources (e.g. Snowflake warehouses)
      provisioned within a data plane.

      Companies can manage and share compute pools, assign them to jobs, and set
      a default compute pool on data planes.
  - name: Connections
    description: Associations between connectors and datasets
  - name: Datasets
    description: >-
      Any kind of data, in any schema, can be pushed into the Narrative Data
      Collaboration Platform as a dataset exactly as it is stored in your own
      system.


      The `datasets` API allows you to manage your datasets.
  - name: Derivations
    description: >-
      Derivation rules describe how the value of one Rosetta Stone attribute can
      be computed from another — for

      example, hashing a raw email into a SHA-256 hashed email. Each rule
      carries a transformation expression that

      reads the source attribute's value through `$source`.


      The `derivations` API allows you to browse the rules your company can use
      — the ones it owns plus the ones

      shared with it through collaborators. Creating and changing them requires
      an `admin` grant on

      `attribute_derivations`, and a rule can only be changed by the company
      that owns it.
  - name: Installations
    description: Installations of Applications for a profile
  - name: Jobs
    description: >-
      Jobs represent an operation done on a given data plane. All jobs today are
      tied to a query that represents a forecast or a materialized view.


      The jobs API provides an interface for interacting with the jobs table,
      which stores various operations involving reading or writing data. This
      API allows users to retrieve detailed information about specific jobs,
      including NQL forecasts and materialized views.
  - name: Mappings
    description: >-
      A mapping is a transformation from a dataset to an attribute. Defining a
      mapping between a dataset and an attribute makes the dataset eligible to
      participate in subscriptions where a buyer is purchasing the target
      attribute.
  - name: Model Inference
    description: Model Inference
  - name: Model Training
    description: >-
      Train machine learning models on datasets, e.g. text classifiers used to
      power attribute mappings.
  - name: Models
    description: >-
      Machine learning models for training and inference.


      Models can be stored in HuggingFace or Narrative repositories and have
      configurable

      collaborator permissions for training and inference access.


      The `models` API allows you to list, retrieve, and update models
      accessible to your company.
  - name: NQL
    description: >-
      Narrative Query Language (NQL) is a specialized, SQL-inspired language
      designed to query and manipulate data within the Narrative platform. While
      it looks and feels much like standard SQL, it offers extended
      functionality and syntax that let you leverage platform-specific
      features—such as referencing datasets by their IDs, creating materialized
      views, or generating forecasts—without having to manage the complexities
      of different query engines behind the scenes. NQL queries can ultimately
      compile down to multiple underlying engines (e.g., Snowflake, Spark) to
      execute your requests efficiently in the Narrative ecosystem.


      Datasets, views, and access rules share one NQL naming namespace per
      company. Use

      `GET /nql/name-availability?name=monthly_purchases` to check whether a
      name is free before creating an object.

      Archiving a dataset, view, or access rule releases its name. Availability
      is a check, not a reservation.
  - name: Profiles
    description: >-
      App profiles are associated with an installation. They represent a
      reference to a configuration that the app can use to save confidential
      information outside of Narrative's control.

      Profiles are currently used to configure settings for connector apps.
  - name: Resources
    description: >-
      Narrative gives you access to managed resources, like your own AWS S3
      bucket, so that you can effortlessly buy and sell data on the platform.


      The `resources` API allows you to manage your resources.
  - name: Schema Inference
    description: >-
      The `schema-inference` API analyzes submitted files to automatically infer
      and return their structure as a dataset schema.
  - name: Uploads
    description: >-
      The `uploads` API allows you to send files to Narrative and use them to
      perform tasks like creating a list or adding data to a dataset.
  - name: Usage
    description: >-
      The `usage` API enables the recording of usage events associated with a
      product.
  - name: Webhooks
    description: >-
      Webhooks push events to a URL you control instead of making you poll for
      them.


      You create a subscription with the endpoint you want events sent to and a
      filter describing which events you

      want. Two kinds of subscription exist: job subscriptions follow the
      lifecycle of Narrative jobs, and app

      subscriptions follow the events a Narrative app reports through `POST
      /apps/events`.


      Creating a subscription returns a `secret`. Narrative sends it back in the
      `X-Narrative-Secret` header on

      every delivery, and comparing the two is how you tell a real callback from
      a forged one — so store it and do

      not share it.


      Deliveries are described under the "Event delivery" webhook below. Return
      any 2xx; anything else is retried

      with exponential backoff, and because a retry reuses the envelope's `id`,
      handlers should be idempotent

      on it.
  - name: Workflows
    description: >-
      The `workflows` API allows you to create, schedule, trigger, and archive
      workflows.

      Workflows are defined using a serverlessworkflow YAML specification.
paths:
  /v2/nql/simulate:
    post:
      tags:
        - NQL
      summary: Simulate an NQL query against access rules
      description: >-
        Check which of a chosen set of access rules would deny a `SELECT` or
        `MERGE` statement, without running

        it. Nothing is stored and no data is read: no job is created and no
        credits are charged.


        The statement runs as the caller's company, in the role of a buyer,
        against the listed access rules

        only. An entry is a stored access rule that the caller's company owns or
        can query, or an inline access

        rule defined in the request. Each access rule moves, with the datasets
        it reads, to a placeholder company

        named by its `placeholder_owner_slug`, and the statement reads it as

        `<placeholder_owner_slug>.<access_rule_name>` or through
        `narrative.rosetta_stone`. The placeholder

        company exists only for this request. Its slug can be the slug of a real
        company, such as the access

        rule's real owner, and that company's data is never involved.


        The statement reads the caller's own active datasets only through
        `company_data`: by id, by name, or all

        of them through `company_data.rosetta_stone`. The caller's own slug is
        not a namespace in a simulation.

        Views and derived mappings are not available, and opt-out datasets and
        dataset statistics are not loaded.

        Query policies are evaluated before opt-out and sampling would apply, so
        neither changes which access

        rules are denied. The policies are checked by the same query policy
        evaluation a normal query goes

        through.


        The response lists, per access rule and query table, the violations that
        denied it. A listed access rule

        that is not in the list was not denied: its policy allowed the
        statement, or the statement did not read

        it.


        Requires a token with read access to subscriptions.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SimulateRequest'
            examples:
              simulate:
                summary: stored and inline access rules
                value:
                  nql: >-
                    SELECT r."email" FROM acme."draft_rule" r JOIN
                    company_data."2001" c ON r."email" = c."email"
                  data_plane_id: f79cbdae-4848-47ca-95e8-69588364d185
                  context:
                    access_rules:
                      - access_rule_id: 4211
                        placeholder_owner_slug: seller
                      - access_rule_id: 4212
                        placeholder_owner_slug: acme
                      - access_rule:
                          name: draft_rule
                          nql: SELECT t."email" FROM company_data."11370" t
                          query_policy:
                            default:
                              projection:
                                mode: allow
                        placeholder_owner_slug: acme
      responses:
        '200':
          description: >-
            The statement compiled. `denied_access_rules` can be empty, which
            means no listed access rule denied the

            statement. A listed access rule that is not in `denied_access_rules`
            was not denied by its policy: it allowed

            the query or no table in the query reached it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SimulateResponse'
              examples:
                simulate:
                  value:
                    denied_access_rules:
                      - index: 0
                        access_rule_id: 4211
                        query_table: narrative.rosetta_stone
                        violations:
                          - type: join_required
                            required_join_keys:
                              - - attribute: email
                                  form: raw
                            reason: >-
                              The query must join this access rule with your
                              company's data on one of the keys its policy
                              requires.
                      - index: 2
                        access_rule_name: draft_rule
                        query_table: acme.draft_rule
                        violations:
                          - type: field_usage
                            field: email
                            usage: projection
                            reason: Field email cannot be selected.
                          - type: field_usage
                            field: phone
                            usage: projection
                            operator: sha256
                            reason: >-
                              Field phone can be selected only through a listed
                              operator, and sha256 is not listed.
        '400':
          description: >-
            The request cannot be simulated as sent. The cases are:


            - The body did not decode, including a `context.access_rules` entry
            that sets both or neither of
              `access_rule_id` and `access_rule`. This returns the `error` / `error_description` shape with
              `error` set to `bad_payload`.
            - An `access_rule_id` does not exist, is archived, or belongs to
            another company that does not let the
              caller query it. This returns an RFC 7807 problem titled `Access Rules Not Queryable` that lists every
              such id.
            - `data_plane_id` does not exist or the company cannot use it. This
            returns an RFC 7807 problem titled
              `Data Plane not found`.
            - The statement did not parse, references a table or column the
            company cannot see, or is
              semantically invalid, for example an unsupported output column type. This returns an RFC 7807
              problem with the title and status `POST /nql/validate` returns for the same problem: 400 for a
              statement that does not parse or reads something the company cannot see, 422 for a semantic error.
            - An inline access rule's `nql` fails the checks of `POST
            /v2/access-rules`, including reading from a
              view dataset. This returns the error `POST /v2/access-rules` returns.

            visit https://docs.narrative.io/guides/nql/troubleshooting for more
            details
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/Response'
                  - $ref: '#/components/schemas/Error'
              examples:
                access_rules_not_queryable:
                  summary: access rules the caller cannot query
                  value:
                    type: null
                    title: Access Rules Not Queryable
                    status: 400
                    detail: >-
                      Access rules 4211 and 4213 can't be used in a simulation
                      because your company can't query them. List only access
                      rules your company owns or can query.
                    instance: /v2/nql/simulate
                    log_id: 5f1c9b2e-7a44-4d18-9c3f-2b6e0a15d7c4
                    debug: null
                data_plane_not_found:
                  summary: unknown or inaccessible data plane
                  value:
                    type: null
                    title: Data Plane not found
                    status: 400
                    detail: f79cbdae-4848-47ca-95e8-69588364d185 data plane not found
                    instance: /v2/nql/simulate
                    log_id: 5f1c9b2e-7a44-4d18-9c3f-2b6e0a15d7c4
                    debug: null
        '403':
          description: >-
            The request is not allowed with the token sent, or no valid token
            was sent.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/Error'
                  - $ref: '#/components/schemas/Response'
        '422':
          description: >-
            The request decoded but cannot be simulated, or the statement is
            semantically invalid. For the cases

            below the problem's `title` is `Invalid Simulation` and `detail`
            names the cause. A semantic error in

            the statement itself returns the problem described under 400, with
            its own title.

            The cases are:


            - `context.access_rules` holds no entries or more than 50.

            - An entry has no `placeholder_owner_slug`.

            - A `placeholder_owner_slug` is not a valid company slug (`a-z`,
            `A-Z`, `0-9` and `_`, at most 256 characters).

            - A `placeholder_owner_slug` is `company_data` or `narrative`.

            - Two access rules over the same dataset have different owners.

            - An `access_rule_id` is listed twice, or two entries share a
            `placeholder_owner_slug` and an access rule name.

            - A stored access rule's `nql` no longer parses.

            - An access rule the caller's company owns, stored or inline, names
            a dataset in its `nql` instead of
              using the dataset id.
            - A listed access rule, stored or inline, is on another data plane
            than the request.

            - A listed access rule, stored or inline, reads a dataset that is
            not active.

            - An inline `query_policy` is not valid for its access rule.

            - The statement is an `INSERT`, `UPDATE`, `DELETE`, `CREATE
            MATERIALIZED VIEW` or `EXPLAIN`.


            visit https://docs.narrative.io/guides/nql/troubleshooting for more
            details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Response'
              examples:
                missing_placeholder_owner_slug:
                  summary: access rule without placeholder_owner_slug
                  value:
                    type: null
                    title: Invalid Simulation
                    status: 422
                    detail: >-
                      context.access_rules[1] needs a placeholder_owner_slug:
                      every access rule is simulated under a placeholder owner
                      company.
                    instance: /v2/nql/simulate
                    log_id: c904b703-d41e-4372-9276-9f4bdc8ad031
                    debug: null
                other_data_plane:
                  summary: access rule on another data plane
                  value:
                    type: null
                    title: Invalid Simulation
                    status: 422
                    detail: >-
                      Access rule 4212 is on another data plane than the
                      request.
                    instance: /v2/nql/simulate
                    log_id: 8d2f6a10-3b57-4e0c-a1f4-6c9e7d2b5a38
                    debug: null
      security:
        - BearerAuth: []
components:
  schemas:
    SimulateRequest:
      type: object
      required:
        - nql
        - data_plane_id
        - context
      properties:
        nql:
          type: string
          description: >-
            The statement to check: a `SELECT`, including `WITH` and `UNION`
            selects, or a `MERGE` into one of the

            caller's datasets. `INSERT`, `UPDATE` and `DELETE` cannot read
            access rules, so they, `CREATE

            MATERIALIZED VIEW` and `EXPLAIN` return 422.


            The statement runs as the caller's company, in the role of a buyer.
            It reads a listed access rule as

            `<placeholder_owner_slug>.<access_rule_name>`, or through
            `narrative.rosetta_stone`. It reads the

            caller's own datasets only through `company_data`: by id, by name,
            or through

            `company_data.rosetta_stone`. The caller's own slug is not a
            namespace in a simulation.
        data_plane_id:
          allOf:
            - $ref: '#/components/schemas/DataPlaneId'
          description: >-
            The data plane the statement is compiled for. Every listed access
            rule, stored or inline, must be on

            this data plane, and the statement reads the caller's datasets only
            from it.
        context:
          $ref: '#/components/schemas/SimulateContext'
    SimulateResponse:
      type: object
      description: >-
        The access rules whose query policy denied the statement. A listed
        access rule that is not in

        `denied_access_rules` was not denied: its policy allowed the statement,
        or the statement did not read it.
      required:
        - denied_access_rules
      properties:
        denied_access_rules:
          type: array
          description: >-
            One entry per access rule and query table it was denied on, in the
            order of `context.access_rules`.

            When the statement reads the same table more than once, such as in a
            self-join, each read that is

            denied has its own entry.
          items:
            $ref: '#/components/schemas/SimulateDenied'
    Response:
      type: object
      description: >-
        An RFC 7807 problem. `title` names the kind of error and `detail`
        explains this occurrence;

        https://docs.narrative.io/guides/nql/troubleshooting walks through the
        NQL titles.
      required:
        - title
        - status
        - detail
        - instance
        - log_id
      properties:
        type:
          description: A URL naming the class of error.
          type:
            - string
            - 'null'
          format: uri
        title:
          type: string
          description: a summary of the error
        status:
          type: integer
          description: http status code
        detail:
          type: string
          description: a longer description of the error
        instance:
          type: string
          description: path of the query
        log_id:
          type: string
          format: uuid
          description: an internal logging id, Narrative can use to help debug a problem.
        debug:
          description: >-
            Extra detail shaped by the error, for example the column and type
            name of an unsupported-type

            error. Null when the error has nothing to add. Most errors only
            include it for admin tokens.
          type:
            - object
            - 'null'
          additionalProperties: true
        app:
          description: >-
            The connector app that raised the error, on errors a connector
            returned. Otherwise null or absent.
          type:
            - string
            - 'null'
      example:
        type: null
        title: Failed to Parse Query
        status: 400
        detail: Invalid query format.
        instance: /nql/validate
        log_id: c06fea02-0950-45c6-aaff-07ab07c0d04c
        debug: null
    Error:
      type: object
      required:
        - error
        - error_description
      properties:
        error:
          type: string
          example: Unauthorized
        error_description:
          type: string
          example: You are not authorized to use this endpoint.
    DataPlaneId:
      type: string
      format: uuid
      description: >-
        A dataplane represent where you would run the query. Your query get
        compiled

        to the SQL dialect that your data engine understands. If you leave it
        blank,

        your query will target Narrative's dataplane on AWS using Apache Spark.
        We

        currently support Snowflake and we plan to support other dataplanes in
        the

        future. See https://next.narrative.io/products/narrative-anywhere for
        more

        details.
    SimulateContext:
      type: object
      description: >-
        The access rules the statement runs against. Apart from the caller's own
        datasets, the statement sees

        only these access rules.
      required:
        - access_rules
      properties:
        access_rules:
          type: array
          minItems: 1
          maxItems: 50
          description: >-
            From 1 to 50 entries. Each entry is either a stored access rule
            (`access_rule_id`) or an inline

            access rule (`access_rule`), and each moves to the placeholder
            company named by its

            `placeholder_owner_slug`.
          items:
            $ref: '#/components/schemas/SimulateAccessRuleEntry'
    SimulateDenied:
      type: object
      description: >-
        An access rule denied on one query table. Set `access_rule_id` for a
        stored access rule and

        `access_rule_name` for an inline one.
      oneOf:
        - required:
            - access_rule_id
        - required:
            - access_rule_name
      required:
        - index
        - query_table
        - violations
      properties:
        index:
          type: integer
          minimum: 0
          description: >-
            The position of the access rule in `context.access_rules`, starting
            at 0.
        access_rule_id:
          type: integer
          description: Present for a stored access rule.
        access_rule_name:
          type: string
          description: Present for an inline access rule.
        query_table:
          type: string
          description: >-
            The table of the statement the access rule was reached through, such
            as

            `<placeholder_owner_slug>.<access_rule_name>`,
            `narrative.rosetta_stone` or

            `<placeholder_owner_slug>.rosetta_stone`.
          example: acme.draft_rule
        violations:
          type: array
          description: >-
            The reasons the access rule was denied on this table, in no
            particular order.
          items:
            $ref: '#/components/schemas/SimulateViolation'
    SimulateAccessRuleEntry:
      type: object
      description: >-
        One access rule in a simulation. Set exactly one of `access_rule_id` and
        `access_rule`, and always set

        `placeholder_owner_slug`. An entry that sets both or neither of the
        first two is rejected.
      properties:
        access_rule_id:
          type: integer
          description: >-
            A stored access rule that the caller's company owns or can query. An
            archived access rule counts as

            not queryable. Every dataset the access rule reads must be active.
        access_rule:
          $ref: '#/components/schemas/SimulateInlineAccessRule'
        placeholder_owner_slug:
          type: string
          description: >-
            The slug of the placeholder company that owns the access rule, and
            the datasets it reads, during this

            simulation. The statement reads the access rule as
            `<placeholder_owner_slug>.<access_rule_name>`.


            The placeholder company exists only for this request. Any valid
            company slug works except

            `company_data` and `narrative`, including the slug of a real
            company, such as the access rule's real

            owner; that company's data is never involved. The slug is compared
            in lower case, and entries with the

            same slug share one placeholder company. A dataset can have only one
            owner, so two access rules that

            read the same dataset need the same `placeholder_owner_slug`.
      required:
        - placeholder_owner_slug
      oneOf:
        - required:
            - access_rule_id
        - required:
            - access_rule
    SimulateViolation:
      type: object
      required:
        - type
        - reason
      properties:
        type:
          type: string
          enum:
            - field_usage
            - join_required
            - invalid_query_policy
          description: >-
            - `field_usage`: the statement uses a field or attribute in a way
            the query policy does not allow.
              `field` names it.
            - `join_required`: the statement does not join as the query policy
            requires. `required_join_keys`
              lists the keys that would satisfy it.
            - `invalid_query_policy`: the access rule's query policy does not
            compile, so it denies every
              statement. It is then the only violation of the access rule on that table.
        field:
          type: string
          description: >-
            Present on `field_usage`. The attribute path for a field read
            through `rosetta_stone`, the column

            path of the access rule for a field read through an access rule
            table.
        usage:
          type: string
          enum:
            - projection
            - group_by
            - join
            - operator
            - derived_attribute
          description: >-
            Present on `field_usage`. How the statement used the field in a way
            the policy does not allow:

            selecting it, grouping by it, joining on it, applying an operator
            the policy does not list, or reading

            it through a derived attribute.
        operator:
          type: string
          description: >-
            Present on `field_usage` when an operator is not listed for the
            field, such as `sha256`.
          example: sha256
        required_join_keys:
          type: array
          description: >-
            Present on `join_required`. Join on all keys of any one group to
            satisfy the policy. Each key has the

            same shape as in the query policy's `join_required_rule`.
          items:
            type: array
            items:
              $ref: '#/components/schemas/JoinKey'
        reason:
          type: string
          description: >-
            A description of the violation. The text can change; do not parse
            it.
    SimulateInlineAccessRule:
      type: object
      description: >-
        An access rule defined in the request instead of stored. It is checked
        the way `POST /v2/access-rules`

        checks a new access rule, and it is not saved. Its `nql` can read only
        the caller's own active datasets,

        not views, and must reference them by id, such as `company_data."2001"`:
        the datasets move to the

        placeholder company, so a dataset name no longer resolves.
      required:
        - name
        - nql
        - query_policy
      properties:
        name:
          $ref: '#/components/schemas/AccessRuleName'
        nql:
          $ref: '#/components/schemas/AccessRuleNQL'
        query_policy:
          $ref: '#/components/schemas/QueryPolicy'
    JoinKey:
      type: object
      description: >-
        One key of a match. Set exactly one of `attribute` and `field`. The
        access rule must select the attribute or

        field. As in `UsageRule`, a field that renames an attribute refers to
        that attribute.
      additionalProperties: false
      required:
        - form
      properties:
        attribute:
          type: string
          description: Rosetta Stone attribute path, such as `email` or `id.value`.
        field:
          type: string
          description: >-
            Access rule column path, such as `hashed_email`. Use a dot for a
            nested property of a column, such as

            `address.zip`.
        form:
          oneOf:
            - type: string
              enum:
                - raw
            - type: object
              additionalProperties: false
              required:
                - operator
              properties:
                operator:
                  type: string
    AccessRuleName:
      type: string
      description: >-
        It should be unique.

        Also should not intersect with Dataset names.

        Must be <= 256 characters and consist of only alphanumeric characters
        and underscores.
    AccessRuleNQL:
      type: string
      description: NQL query of access rule.
    QueryPolicy:
      type: object
      description: >-
        Limits how a querying company may use the attributes and fields this
        access rule selects. An attribute is a

        Rosetta Stone attribute that the access rule selects from
        `_rosetta_stone`. A field is any other column of the

        access rule, such as a dataset column it selects directly. A query that
        breaks the policy reads no rows from the

        access rule.
      additionalProperties: false
      properties:
        default:
          description: >-
            Rules for every attribute and field that no `usage_rules` entry
            names. A usage left out is denied.
          oneOf:
            - $ref: '#/components/schemas/UsageRules'
            - type: 'null'
        usage_rules:
          oneOf:
            - type: array
              items:
                $ref: '#/components/schemas/UsageRule'
            - type: 'null'
        join_required_rule:
          oneOf:
            - $ref: '#/components/schemas/JoinRequiredRule'
            - type: 'null'
    UsageRules:
      type: object
      additionalProperties: false
      properties:
        projection:
          oneOf:
            - $ref: '#/components/schemas/ProjectionRule'
            - type: 'null'
        group_by:
          oneOf:
            - $ref: '#/components/schemas/GroupByRule'
            - type: 'null'
        join:
          oneOf:
            - $ref: '#/components/schemas/JoinRule'
            - type: 'null'
    UsageRule:
      type: object
      description: >-
        Rules for one attribute or field. Set exactly one of `attribute` and
        `field`. The access rule must select the

        attribute or field. A field that renames an attribute refers to that
        attribute. For example, when the access rule

        selects `_rosetta_stone.email as email`, `{"field": "email"}` and
        `{"attribute": "email"}` name the same column,

        so a policy can have a rule for only one of them.
      additionalProperties: false
      properties:
        attribute:
          type: string
          description: Rosetta Stone attribute path, such as `email` or `id.value`.
        field:
          type: string
          description: >-
            Access rule column path, such as `hashed_email`. Use a dot for a
            nested property of a column, such as

            `address.zip`.
        projection:
          $ref: '#/components/schemas/ProjectionRule'
        group_by:
          $ref: '#/components/schemas/GroupByRule'
        join:
          $ref: '#/components/schemas/JoinRule'
    JoinRequiredRule:
      type: object
      description: >-
        Requires every query to inner join this access rule to a dataset the
        querying company owns, matching on the keys

        of one `match` entry.
      additionalProperties: false
      required:
        - match
      properties:
        match:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/JoinMatch'
    ProjectionRule:
      type: object
      additionalProperties: false
      required:
        - mode
      properties:
        mode:
          $ref: '#/components/schemas/Mode'
        scalar_operators:
          allOf:
            - $ref: '#/components/schemas/OperatorList'
          description: Scalar functions, such as `SHA2` or `UPPER`.
        aggregate_operators:
          allOf:
            - $ref: '#/components/schemas/OperatorList'
          description: >-
            Aggregate functions, such as `COUNT`, `SUM`, `COUNT_DISTINCT`,
            `APPROX_COUNT_DISTINCT`.
        external_operators:
          allOf:
            - $ref: '#/components/schemas/OperatorList'
          description: >-
            Functions that send values outside the query: `AI_COMPLETE`,
            `AI_CONVERSATION`, `AI_EMBED`,

            `CALL_MODEL_FUNCTION`.
    GroupByRule:
      type: object
      additionalProperties: false
      required:
        - mode
      properties:
        mode:
          $ref: '#/components/schemas/Mode'
        scalar_operators:
          $ref: '#/components/schemas/OperatorList'
    JoinRule:
      type: object
      additionalProperties: false
      required:
        - mode
      properties:
        mode:
          $ref: '#/components/schemas/Mode'
        scalar_operators:
          $ref: '#/components/schemas/OperatorList'
    JoinMatch:
      type: object
      additionalProperties: false
      required:
        - keys
      properties:
        keys:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/JoinKey'
    Mode:
      type: string
      enum:
        - allow
        - deny
        - restrict
      description: >-
        `allow` permits every use. `deny` permits none. `restrict` permits only
        the functions the rule's lists name, and

        never the raw value.
    OperatorList:
      oneOf:
        - type: array
          items:
            type: string
        - type: 'null'
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.