Bubble Data API

REST API exposing the Bubble app database. Supports search with constraints, cursor-based pagination, single-record CRUD, bulk create (up to 1,000 records), and metadata discovery. Authentication uses bearer tokens (admin tokens bypass privacy rules; user tokens enforce them). Endpoints are available on both live and `version-test` (development) environments.

OpenAPI Specification

bubble-data-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: Bubble Data API
  description: |
    The Bubble Data API exposes the database of a Bubble app as a REST interface.
    External systems can read, search, create, modify, replace, and delete records
    of any data type defined in a Bubble app, with optional pagination, sorting,
    and search constraints. Authentication uses bearer tokens (admin API tokens
    bypass privacy rules; user tokens enforce them). Endpoints exist for live and
    development (`version-test`) environments.
  version: '1.1'
  contact:
    name: Bubble Support
    url: https://bubble.io/contact
  license:
    name: Bubble Terms of Service
    url: https://bubble.io/legal/terms-of-service
servers:
  - url: https://{appname}.bubbleapps.io/api/1.1
    description: Live App on Bubble subdomain
    variables:
      appname:
        default: myapp
        description: Bubble app name
  - url: https://{appname}.bubbleapps.io/version-test/api/1.1
    description: Development (version-test) on Bubble subdomain
    variables:
      appname:
        default: myapp
        description: Bubble app name
  - url: https://{customDomain}/api/1.1
    description: Live App on a custom domain
    variables:
      customDomain:
        default: example.com
        description: Custom domain pointing to the Bubble app
security:
  - BearerAuth: []
tags:
  - name: Data
    description: Read, search, create, modify, replace, and delete data things.
paths:
  /obj/{typename}:
    parameters:
      - $ref: '#/components/parameters/Typename'
    get:
      tags:
        - Data
      summary: Search Things
      description: |
        Returns a list of records of the given data type. Supports search constraints,
        cursor-based pagination, sorting, and field projection.
      operationId: searchThings
      parameters:
        - name: constraints
          in: query
          description: |
            JSON-encoded array of search constraints. Each constraint is an object
            with `key`, `constraint_type`, and `value`. Supported constraint types:
            equals, not equal, is_empty, is_not_empty, text contains,
            not text contains, greater than, less than, in, not in, contains,
            not contains, geographic_search.
          schema:
            type: string
          example: '[{"key":"unitname","constraint_type":"equals","value":"Studio 5"}]'
        - name: cursor
          in: query
          description: Zero-based start position for the page.
          schema:
            type: integer
            minimum: 0
        - name: limit
          in: query
          description: Maximum results per request (default and max 100 per page).
          schema:
            type: integer
            minimum: 1
            maximum: 100
        - name: sort_field
          in: query
          description: Field name to sort the results by.
          schema:
            type: string
        - name: descending
          in: query
          description: Sort direction. `true` for descending, `false` for ascending.
          schema:
            type: boolean
        - name: additional_sort_fields
          in: query
          description: JSON-encoded array of additional sort fields and directions.
          schema:
            type: string
        - name: exclude_remaining
          in: query
          description: Skip total-record counting for performance.
          schema:
            type: boolean
      responses:
        '200':
          description: Search response with paginated results.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
    post:
      tags:
        - Data
      summary: Create Thing
      description: Create a single new record of the given data type.
      operationId: createThing
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Thing'
      responses:
        '201':
          description: Created. Returns the unique id assigned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
  /obj/{typename}/bulk:
    parameters:
      - $ref: '#/components/parameters/Typename'
    post:
      tags:
        - Data
      summary: Bulk Create Things
      description: |
        Create up to 1,000 new records in a single request. The request body
        is one JSON object per line (newline-delimited JSON).
      operationId: bulkCreateThings
      requestBody:
        required: true
        content:
          text/plain:
            schema:
              type: string
              description: Newline-delimited JSON, one object per line, max 1,000 lines.
      responses:
        '200':
          description: Newline-delimited JSON results, one per submitted object.
          content:
            text/plain:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
  /obj/{typename}/{uid}:
    parameters:
      - $ref: '#/components/parameters/Typename'
      - $ref: '#/components/parameters/Uid'
    get:
      tags:
        - Data
      summary: Get Thing
      description: Retrieve a single record by its unique id.
      operationId: getThing
      responses:
        '200':
          description: The requested record.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ThingResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
    patch:
      tags:
        - Data
      summary: Modify Thing
      description: Partially update a record. Only the provided fields are changed.
      operationId: modifyThing
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Thing'
      responses:
        '204':
          description: No Content. Modification successful.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
    put:
      tags:
        - Data
      summary: Replace Thing
      description: Fully replace the record with the supplied object.
      operationId: replaceThing
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Thing'
      responses:
        '204':
          description: No Content. Replacement successful.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
    delete:
      tags:
        - Data
      summary: Delete Thing
      description: Permanently delete a record.
      operationId: deleteThing
      responses:
        '204':
          description: No Content. Deletion successful.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
  /meta:
    get:
      tags:
        - Data
      summary: Get Data Type Metadata
      description: |
        Returns the data types and their fields exposed via the Data API for the
        current environment. Useful for client code generation and discovery.
      operationId: getMetadata
      responses:
        '200':
          description: Metadata response listing exposed types and fields.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Token
      description: |
        Send the API token in the `Authorization` header as `Bearer <token>`.
        Admin tokens bypass privacy rules; user tokens (returned by the
        `Log the User in` workflow action) enforce privacy rules per user.
  parameters:
    Typename:
      name: typename
      in: path
      required: true
      description: Data type name in lowercase with spaces removed.
      schema:
        type: string
      example: shopping_cart
    Uid:
      name: uid
      in: path
      required: true
      description: Unique id of the record.
      schema:
        type: string
      example: 1503408875694x944431186090727200
  schemas:
    Thing:
      type: object
      description: A single record. Field names match the data type's fields in the Bubble app.
      additionalProperties: true
    ThingResponse:
      type: object
      properties:
        response:
          $ref: '#/components/schemas/Thing'
    SearchResponse:
      type: object
      properties:
        response:
          type: object
          properties:
            cursor:
              type: integer
              description: Position of the first returned item.
            results:
              type: array
              items:
                $ref: '#/components/schemas/Thing'
            remaining:
              type: integer
              description: Records remaining beyond the returned page.
            count:
              type: integer
              description: Number of records on this page.
    CreateResponse:
      type: object
      properties:
        status:
          type: string
          example: success
        id:
          type: string
          description: Unique id assigned to the new record.
    Error:
      type: object
      properties:
        statusCode:
          type: integer
        body:
          type: object
          properties:
            status:
              type: string
            message:
              type: string
  responses:
    BadRequest:
      description: Invalid request payload, missing fields, or malformed constraints.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid bearer token, or token lacks required privileges.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: The requested record does not exist or the type is not exposed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: Too many requests. The plan-level requests-per-minute limit has been exceeded.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'