Acquia Content API

The stable JSON:API 1.1 surface shared by every Acquia Source CMS site, plus the OAuth 2.0 endpoints that issue the tokens it accepts. Ten operations cover token issuance, the authorization redirect, the resource-type index, and JSON:API collection/entry/relationship reads and writes. The base URL is the customer's own site, so servers[] is templated on {siteUrl}; the per-bundle endpoint list is generated on each site at API > OpenAPI documentation.

Operations 10

POST /oauth/token Issue an access token #
GET /oauth/authorize Start the authorization_code grant #
GET /api List available resource endpoints #
GET /api/{entityType}/{bundle} List entries of a bundle #
POST /api/{entityType}/{bundle} Create an entry #
GET /api/{entityType}/{bundle}/{uuid} Get one entry #
PATCH /api/{entityType}/{bundle}/{uuid} Update an entry #
DELETE /api/{entityType}/{bundle}/{uuid} Delete an entry #
GET /api/{entityType}/{bundle}/{uuid}/{field} Get related entries #
GET /api/{entityType}/{bundle}/{uuid}/relationships/{field} Get a relationship's linkage #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/acquia-content-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no email required.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

acquia-content-api-openapi.yaml Raw ↑
openapi: 3.1.0
info:
  title: Acquia Content API
  version: "1.1"
  description: >
    The stable JSON:API surface shared by every Source CMS site, plus the OAuth 2.0
    authentication endpoints that issue the tokens it accepts. Base URL, endpoint
    shapes, headers, query parameters, and error codes are identical on every site;
    a site's live per-bundle endpoint list is generated on the site itself at
    `API > OpenAPI documentation`. Values were verified against a live site. Captured
    request and response shapes for each endpoint are in the
    [Content API reference](/source-cms/reference/content-api/); the grant types,
    scopes, and token lifetimes are in the
    [authentication reference](/source-cms/reference/authentication/).
servers:
  - url: "{siteUrl}"
    description: >
      Your site's base URL, the canonical ACQUIA_SITE_URL environment variable, with
      no trailing slash. Source CMS serves JSON:API under /api; headless Cloud Platform
      sites serve it under /jsonapi.
    variables:
      siteUrl:
        default: https://your-site.example.com
        description: The ACQUIA_SITE_URL environment variable (no trailing slash).
tags:
  - name: Authentication
    description: OAuth 2.0 token and authorization endpoints.
  - name: Content
    description: JSON:API resource endpoints for reading and writing entries.
paths:
  /oauth/token:
    post:
      tags: [Authentication]
      operationId: issueToken
      summary: Issue an access token
      description: >
        Issues access tokens for all three grant types. The request body is
        form-encoded. `client_credentials` is server-to-server; `authorization_code`
        exchanges a code from `GET /oauth/authorize`; `refresh_token` exchanges a
        refresh token. Only `authorization_code` and `refresh_token` return a
        `refresh_token`; `client_credentials` never does.
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              required: [grant_type, client_id, client_secret]
              properties:
                grant_type:
                  type: string
                  enum: [client_credentials, authorization_code, refresh_token]
                client_id:
                  type: string
                  description: The API client's ID (ACQUIA_CLIENT_ID).
                client_secret:
                  type: string
                  description: The API client's secret (ACQUIA_CLIENT_SECRET).
                scope:
                  type: string
                  description: >
                    Space-separated subset of the client's selected scopes. Omit to
                    receive every selected scope. client_credentials and
                    authorization_code only.
                code:
                  type: string
                  description: The authorization code from the redirect (authorization_code grant only).
                redirect_uri:
                  type: string
                  description: The same redirect URI used at /oauth/authorize (authorization_code grant only).
                refresh_token:
                  type: string
                  description: The refresh token to exchange (refresh_token grant only).
            examples:
              clientCredentials:
                summary: client_credentials
                value:
                  grant_type: client_credentials
                  client_id: "$ACQUIA_CLIENT_ID"
                  client_secret: "$ACQUIA_CLIENT_SECRET"
      responses:
        "200":
          description: A newly issued access token.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResponse"
              example:
                token_type: Bearer
                expires_in: 300
                access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1Ni
        "400":
          description: >
            Invalid request, most commonly `invalid_scope` when the `scope` parameter
            names a scope that does not exist or is not selected on the client.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OAuthError"
              example:
                error: invalid_scope
                error_description: The requested scope is invalid, unknown, or malformed
                hint: "Check the `content:read` scope"
        "401":
          description: "Client authentication failed (`invalid_client`): the client ID or secret is wrong."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OAuthError"
              example:
                error: invalid_client
                error_description: Client authentication failed
  /oauth/authorize:
    get:
      tags: [Authentication]
      operationId: authorize
      summary: Start the authorization_code grant
      description: >
        Redirects the user to log in and grant permissions, then redirects back to
        `redirect_uri` with a temporary authorization code to exchange at
        `POST /oauth/token`. Used only by the authorization_code grant.
      parameters:
        - name: response_type
          in: query
          required: true
          schema: { type: string, enum: [code] }
          description: The literal value `code`.
        - name: client_id
          in: query
          required: true
          schema: { type: string }
          description: The API client's ID.
        - name: redirect_uri
          in: query
          required: true
          schema: { type: string }
          description: Must match one of the client's configured Redirect URIs.
        - name: scope
          in: query
          required: false
          schema: { type: string }
          description: Space-separated subset of the client's selected scopes.
      responses:
        "302":
          description: Redirect to `redirect_uri` carrying the temporary authorization code.
  /api:
    get:
      tags: [Content]
      operationId: apiRoot
      summary: List available resource endpoints
      description: >
        Returns the index of resource endpoints available on the site, keyed by
        resource type (for example `node--article`). No version segment appears in the
        path; every response reports `jsonapi.version` `1.1`.
      security:
        - bearerAuth: []
      responses:
        "200":
          description: The API root document.
          content:
            application/vnd.api+json:
              schema: { type: object }
        "401":
          $ref: "#/components/responses/Unauthorized"
  /api/{entityType}/{bundle}:
    parameters:
      - $ref: "#/components/parameters/entityType"
      - $ref: "#/components/parameters/bundle"
    get:
      tags: [Content]
      operationId: listEntries
      summary: List entries of a bundle
      description: >
        A collection of entries of one bundle, for example `/api/node/article`.
        `data` is an array. `meta.count` is the collection total including entries the
        request cannot see, so `data` can be shorter than `meta.count`, or empty; check
        `meta.omitted` and follow `links.next`.
      security:
        - bearerAuth: []
        - {}
      parameters:
        - $ref: "#/components/parameters/filter"
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/include"
        - $ref: "#/components/parameters/page"
        - $ref: "#/components/parameters/sort"
      responses:
        "200":
          description: A JSON:API collection document.
          content:
            application/vnd.api+json:
              schema:
                $ref: "#/components/schemas/CollectionDocument"
        "401":
          $ref: "#/components/responses/Unauthorized"
    post:
      tags: [Content]
      operationId: createEntry
      summary: Create an entry
      description: >
        Requires the site's allowed-operations setting (`API > JSON:API`) set to
        "Read and write" and a token whose client has the `content:administer` scope.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/vnd.api+json:
            schema:
              $ref: "#/components/schemas/EntityDocument"
      responses:
        "201":
          description: The created entry.
          content:
            application/vnd.api+json:
              schema:
                $ref: "#/components/schemas/EntityDocument"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
  /api/{entityType}/{bundle}/{uuid}:
    parameters:
      - $ref: "#/components/parameters/entityType"
      - $ref: "#/components/parameters/bundle"
      - $ref: "#/components/parameters/uuid"
    get:
      tags: [Content]
      operationId: getEntry
      summary: Get one entry
      description: One entry addressed by its UUID (the `id` in every response). `data` is a single object.
      security:
        - bearerAuth: []
        - {}
      parameters:
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/include"
      responses:
        "200":
          description: A JSON:API entity document.
          content:
            application/vnd.api+json:
              schema:
                $ref: "#/components/schemas/EntityDocument"
        "401":
          $ref: "#/components/responses/Unauthorized"
    patch:
      tags: [Content]
      operationId: updateEntry
      summary: Update an entry
      description: Requires writes enabled and the `content:administer` scope (same as POST).
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/vnd.api+json:
            schema:
              $ref: "#/components/schemas/EntityDocument"
      responses:
        "200":
          description: The updated entry.
          content:
            application/vnd.api+json:
              schema:
                $ref: "#/components/schemas/EntityDocument"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
    delete:
      tags: [Content]
      operationId: deleteEntry
      summary: Delete an entry
      description: Requires writes enabled and the `content:administer` scope (same as POST).
      security:
        - bearerAuth: []
      responses:
        "204":
          description: The entry was deleted.
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
  /api/{entityType}/{bundle}/{uuid}/{field}:
    parameters:
      - $ref: "#/components/parameters/entityType"
      - $ref: "#/components/parameters/bundle"
      - $ref: "#/components/parameters/uuid"
      - name: field
        in: path
        required: true
        schema: { type: string }
        description: A relationship field machine name.
    get:
      tags: [Content]
      operationId: getRelated
      summary: Get related entries
      description: The referenced entries themselves, with full attributes, that a relationship field points at.
      security:
        - bearerAuth: []
        - {}
      responses:
        "200":
          description: A JSON:API document of the related entries.
          content:
            application/vnd.api+json:
              schema: { type: object }
        "401":
          $ref: "#/components/responses/Unauthorized"
  /api/{entityType}/{bundle}/{uuid}/relationships/{field}:
    parameters:
      - $ref: "#/components/parameters/entityType"
      - $ref: "#/components/parameters/bundle"
      - $ref: "#/components/parameters/uuid"
      - name: field
        in: path
        required: true
        schema: { type: string }
        description: A relationship field machine name.
    get:
      tags: [Content]
      operationId: getRelationship
      summary: Get a relationship's linkage
      description: The linkage only (type + id identifiers, no attributes). Use it to read or rewrite what an entry points at without fetching the targets.
      security:
        - bearerAuth: []
        - {}
      responses:
        "200":
          description: A JSON:API relationship document.
          content:
            application/vnd.api+json:
              schema: { type: object }
        "401":
          $ref: "#/components/responses/Unauthorized"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >
        `Authorization: Bearer <token>` with one space after Bearer. Tokens come from
        POST /oauth/token. Not required for published-content GETs when the site's
        `Public access` (`API > JSON:API`) is Yes.
    oauth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://your-site.example.com/oauth/token
          scopes:
            "content:administer": Create, update, and delete entries over JSON:API.
        authorizationCode:
          authorizationUrl: https://your-site.example.com/oauth/authorize
          tokenUrl: https://your-site.example.com/oauth/token
          scopes:
            "content:administer": Create, update, and delete entries over JSON:API.
  parameters:
    entityType:
      name: entityType
      in: path
      required: true
      schema: { type: string, example: node }
      description: An entity type machine name (for example `node`, `media`, `taxonomy_term`).
    bundle:
      name: bundle
      in: path
      required: true
      schema: { type: string, example: article }
      description: A bundle machine name (for example `article`). The
        [content model reference](/source-cms/reference/content-model/#entity-types-and-bundles)
        maps each entity type to its bundle term and endpoint pattern.
    uuid:
      name: uuid
      in: path
      required: true
      schema: { type: string, format: uuid }
      description: The entry's UUID, the `id` member of every response.
    filter:
      name: filter
      in: query
      required: false
      style: deepObject
      explode: true
      schema: { type: object }
      description: >
        Match entries by field value. Short form `filter[field]=value` (equality) or
        canonical form with `[condition][path]`, `[condition][operator]`,
        `[condition][value]`. Operators: =, <>, >, >=, <, <=, STARTS_WITH, CONTAINS,
        ENDS_WITH, IN, NOT IN, BETWEEN, NOT BETWEEN, IS NULL, IS NOT NULL. Date fields
        compare as UNIX timestamps. Field paths use machine names. Every operator is
        shown with a worked example in the
        [query parameter reference](/source-cms/reference/query-parameters/#operators).
    fields:
      name: fields
      in: query
      required: false
      style: deepObject
      explode: true
      schema: { type: object }
      description: "Sparse fieldsets: `fields[node--article]=title,created` limits returned fields per type."
    include:
      name: include
      in: query
      required: false
      schema: { type: string }
      description: "Comma-separated relationship paths to embed in `included`, for example `image,tags`."
    page:
      name: page
      in: query
      required: false
      style: deepObject
      explode: true
      schema: { type: object }
      description: "Pagination: `page[limit]` and `page[offset]`."
    sort:
      name: sort
      in: query
      required: false
      schema: { type: string }
      description: "Comma-separated field machine names; prefix with `-` for descending, for example `-created`."
  responses:
    Unauthorized:
      description: >
        Missing, malformed, or expired token. Access tokens live 300 seconds. The
        diagnostic is in the `WWW-Authenticate` response header; the body may be HTML,
        not JSON.
      content:
        application/vnd.api+json:
          schema:
            $ref: "#/components/schemas/ErrorDocument"
    Forbidden:
      description: >
        The token is valid but lacks the required scope (for example writing without
        `content:administer`). The JSON:API error `detail` names the missing permission.
      content:
        application/vnd.api+json:
          schema:
            $ref: "#/components/schemas/ErrorDocument"
          example:
            errors:
              - status: "403"
                detail: "The 'administer nodes' permission is required."
  schemas:
    TokenResponse:
      type: object
      required: [token_type, expires_in, access_token]
      properties:
        token_type: { type: string, const: Bearer }
        expires_in: { type: integer, description: Access token lifetime in seconds (300). }
        access_token: { type: string }
        refresh_token:
          type: string
          description: Returned by authorization_code and refresh_token grants only; never by client_credentials.
    OAuthError:
      type: object
      properties:
        error: { type: string }
        error_description: { type: string }
        hint: { type: string }
    ResourceObject:
      type: object
      properties:
        type: { type: string, example: node--article }
        id: { type: string, format: uuid }
        attributes: { type: object }
        relationships: { type: object }
    CollectionDocument:
      type: object
      properties:
        jsonapi:
          type: object
          properties:
            version: { type: string, const: "1.1" }
        data:
          type: array
          items:
            $ref: "#/components/schemas/ResourceObject"
        meta:
          type: object
          properties:
            count: { type: integer }
        links: { type: object }
        included:
          type: array
          items:
            $ref: "#/components/schemas/ResourceObject"
    EntityDocument:
      type: object
      properties:
        jsonapi:
          type: object
          properties:
            version: { type: string, const: "1.1" }
        data:
          $ref: "#/components/schemas/ResourceObject"
        links: { type: object }
        included:
          type: array
          items:
            $ref: "#/components/schemas/ResourceObject"
    ErrorDocument:
      type: object
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              status: { type: string }
              title: { type: string }
              detail: { type: string }