New guide: AI is in production. Is your governance?

Announcing Visual Copilot - Figma to production in half the time

Builder.io
Builder.io
Contact sales

New guide: AI is in production. Is your governance?

Announcing Visual Copilot - Figma to production in half the time

Use Builder's Admin API, a GraphQL API, with back-end servers or for trusted parties performing administrative tasks. The Admin API is separate from the public Content API, which is for consuming Builder content.

  • Query and modify data within your Builder Space using the GraphQL API.
  • The Admin SDK can also be used to interact with some features of the GraphQL API.

Choose whether you will access the API with the Node.js SDK or directly through the API. For more details on the Node.js SDK, see Builder's Admin SDK package repository on GitHub.

If you choose access through the GraphQL API, all Admin API queries use the following endpoint.

https://cdn.builder.io/api/v2/admin

You can also use the GraphQL Explorer to access the API through your web browser.

Before using any operation, authenticate with the Builder.io API.

To authenticate, include the following Authorization header, replacing BUILDER_PRIVATE_KEY with your Builder's private Space key. This key should begin with the letters bpk.

import { createAdminApiClient } from '@builder.io/admin-sdk';
const adminSDK = createAdminApiClient(process.env.BUILDER_PRIVATE_KEY);

For more information about creating and organizing private keys, see Managing Private Keys.

The following operations are to be used to query and manage a specific Builder Space.

Get the current settings for your Builder Space. For more details, see Spaces Overview.

Query

const response = await adminSDK
  .query({
    settings: true,
  });

Response

{
  "data": {
    "settings": { ... }
  }
}

Replace every custom targeting attribute for the current space while preserving the existing locale definition.

Query:

const result = await adminSDK
  .chain.mutation.setCustomTargetingAttributes({
    attributes: [
      {
        key: "plan",
        schema: {
          type: "string",
          enum: ["free", "pro", "enterprise"]
        }
      }
    ]
  })
  .execute();

Response:

{
  "data": {
    "setCustomTargetingAttributes": [
      {
        "key": "locale",
        "schema": { "type": "string", "enum": ["en-US"] }
      },
      {
        "key": "plan",
        "schema": { "type": "string", "enum": ["free", "pro", "enterprise"] }
      }
    ]
  }
}

Remove a single non-locale attribute.

Query:

const result = await adminSDK
  .chain.mutation.deleteCustomTargetingAttribute({
    key: "plan"
  })
  .execute();

Response:

{
  "data": {
    "deleteCustomTargetingAttribute": [
      { "key": "device" }
    ]
  }
}

Create or update a single attribute, except locale.

Query:

const result = await adminSDK
  .chain.mutation.upsertCustomTargetingAttribute({
    key: "device",
    schema: {
      type: "string",
      enum: ["mobile", "desktop"]
    }
  })
  .execute();

Response:

{
  "data": {
    "upsertCustomTargetingAttribute": [
      { "key": "device", "schema": { "type": "string", "enum": ["mobile", "desktop"] } }
    ]
  }
}

Remove a locale value and clean up related groups.

Query:

const result = await adminSDK
  .chain.mutation.setSpaceLocales({
    locales: ["en-US", "de-DE", "es-ES"]
  })
  .execute();

Response:

{
  "data": {
    "setSpaceLocales": {
      "enum": ["en-US", "de-DE", "es-ES"]
    }
  }
}

Add or update a locale entry, optionally attaching descriptions and groups.

Query:

const result = await adminSDK
  .chain.mutation.upsertSpaceLocale({
    locale: {
      name: "fr-FR",
      description: "French",
      groups: ["eu"]
    }
  })
  .execute();

Response:

{
  "data": {
    "upsertSpaceLocale": {
      "enum": ["en-US", "fr-FR"],
      "descriptions": [
        { "name": "en-US", "description": "English" },
        { "name": "fr-FR", "description": "French", "groups": ["eu"] }
      ]
    }
  }
}

Remove a locale value and clean up related groups.

Query:

const result = await adminSDK
  .chain.mutation.deleteSpaceLocale({
    locale: "fr-FR"
  })
  .execute();

Response:

{
  "data": {
    "deleteSpaceLocale": {
      "enum": ["en-US"]
    }
  }
}

Replace the complete set of locale groups.

Query:

const result = await adminSDK
  .chain.mutation.setSpaceLocaleGroups({
    groups: [
      { name: "amer", defaultLocale: "en-US" },
      { name: "emea", defaultLocale: "en-GB" }
    ]
  })
  .execute();

Response:

{
  "data": {
    "setSpaceLocaleGroups": {
      "groups": {
        "amer": "en-US",
        "emea": "en-GB"
      }
    }
  }
}

Create or update a locale group with a default locale.

Query:

const result = await adminSDK
  .chain.mutation.upsertSpaceLocaleGroup({
    name: "emea",
    defaultLocale: "en-GB"
  })
  .execute();

Response:

{
  "data": {
    "upsertSpaceLocaleGroup": {
      "groups": { "emea": "en-GB" }
    }
  }
}

Remove a locale group and associated memberships.

Query:

const result = await adminSDK
  .chain.mutation.deleteSpaceLocaleGroup({
    name: "emea"
  })
  .execute();

Response:

{
  "data": {
    "deleteSpaceLocaleGroup": {
      "groups": {}
    }
  }
}

Persist responsive breakpoints with validation (integers, ≥2px spacing).

Query:

const result = await adminSDK
  .chain.mutation.setSpaceBreakpoints({
    breakpoints: {
      xsmall: 360,
      small: 640,
      medium: 1024
    }
  })
  .execute();

Response:

{
  "data": {
    "setSpaceBreakpoints": {
      "xsmall": 360,
      "small": 640,
      "medium": 1024
    }
  }
}

Retrieve one or more data models from your Builder Space. For more details on models in Builder, see Models Intro.

To get all models from your Builder Space, use the following query.

Query

const response = await adminSDK
  .query({
    models: {
      id: true,
      fields: true,
    },
  });

Response

{
  "data": {
    "models": [
      ...
    ]
  }
}

To get one model by ID from your Builder Space, use the following query replacing "your-model-id" with your model's unique ID.

Query

const response = await adminSDK
  .query({
    model: {
      id: 'your-model-id',
      arguments: {
        id: 'your-model-id'
      },
      properties: {
        id: true,
        name: true,
        fields: true
      }
    },
  });

Response

{
  "data": {
    "models": {
      "id": "MODEL-ID",
      "name": "headline",
      "kind": "component",
      "fields": [
        {
          name: "Headline",
          type: "text",
          required: true,
        }
      ]
    }
  }
}

Create a new model within your Builder Space.

When creating a new model, you must include a name and kind. The fields key must also be present and have a value that is an array.

Query

const result = await adminSDK
  .chain.mutation.addModel({
    body: {
      name: "headline",
      kind: "component",
      fields: [
        {
          name: "Headline",
          type: "text",
          required: true
        }
      ]
    }
  })
  .execute();

Response

{
  "data": {
    "addModel": {
      "id": "...",
      "name": "headline",
      "kind": "component",
      "fields": [
        {
          name: "Headline",
          type: "text",
          required: true,
        }
      ]
    }
  }
}

Update an existing model within your Builder Space.

To update a model by ID from your Builder Space, use the following query replacing "your-model-id" with your model's unique ID. With this query, you may update any fields within the model.

Query

const result = await adminSDK
  .chain.mutation.updateModel({
    body: {
      id: "your-model-id",
      data: {
        fields: [
          {
            name: "Headline",
            type: "text",
            required: true
          },
          {
            name: "Subheadline",
            type: "text",
            required: false
          }
        ]
      }
    }
  })
  .execute();

Response

{
  "data": {
    "updateModel": {
      "id": "MODEL-ID",
      "name": "headline",
      "fields": [
        {
          "name": "Headline",
          "type": "text",
          "required": true
        },
        {
          "name": "Subheadline",
          "type": "text",
          "required": false
        }
      ]
    }
  }
}

Delete an existing model within your Builder Space. This operation is not reversible.

To delete a model by ID from your Builder Space, use the following query replacing "your-model-id" with your model's unique ID.

Query

const result = await adminSDK
  .chain.mutation.deleteModel({
    id: "your-model-id"
  })
  .execute();

Response

{
  "data": {
    "deleteModel": null
  }
}

Folders are used within Builder to organize content entries. For more details, see Managing Content.

To get all folders and their content entries' IDs from your Builder Space, use the following query.

Query

const response = await adminSDK
  .query({
    getFolders: {
      id: true,
      name: true,
      description: true,
      entries: true
    }
  });

Response

{
  "data": {
    "getFolders": [
      {
        "id": "...",
        "name": "My Folder",
        "description": "...",
        "entries": [
          "...",
          "..."
        ]
      }
    ]
  }
}

To get one folder by ID from your Builder Space, use the following query replacing "your-folder-id" with your model's unique ID.

Query

const response = await adminSDK
  .query({
    getFolder: {
      arguments: {
        id: "your-folder-id"
      },
      properties: {
        name: true,
        entries: true
      }
    }
  });

Response

{
  "data": {
    "getFolder": {
      "id": "FOLDER-ID",
      "name": "My Folder",
      "description": "...",
      "entries": [
        "...",
        "..."
      ]
    }
  }
}

Assets refer to media content uploaded to Builder. For more details on assets, see Asset Library.

To get all assets from your Builder Space, use the following query.

Query

const response = await adminSDK
  .query({
    assets: {
      id: true,
      name: true,
      url: true,
      bytes: true,
      lastUsed: true,
      type: true,
      folders: true,
      createdDate: true
    }
  });

Response

{
  "data": {
    "assets": [
      {
        "id": "...",
        "name": "My Image",
        "url": "...",
        "bytes": 380892,
        "lastUsed": 1745956615894,
        "type": "image/jpeg",
        "folders": ["folder-id-1", "folder-id-2"],
        "createdDate": "2024-01-15T10:30:00Z"
      }
    ]
  }
}

Use the following query to sort your assets by a particular key, such as the asset's name.

Query

const response = await adminSDK
  .query({
    assets: [
      {
        input: {
          sort: {
            name: "-1" // or 1
          }
        }
      },
      {
        id: true,
        name: true,
        url: true,
        bytes: true,
        lastUsed: true,
        type: true,
        folders: true
      }
    ]
  });

Response

{
  "data": {
    "assets": [
      {
        "id": "...",
        "name": "My Image",
        "url": "...",
        "bytes": 380892,
        "lastUsed": 1745956615894,
        "type": "image/jpeg",
        "folders": ["folder-id-1", "folder-id-2"],
        "createdDate": "2024-01-15T10:30:00Z"
      }
    ]
  }
}

To filter assets by media type (such as images, videos, or specific formats), use the type field. Note that this corresponds to the MIME type of the asset.

Query

const response = await adminSDK
  .query({
    assets: [
      {
        input: {
          query: {
            type: { $eq: "image/svg+xml" }
          },
          sort: {
            createdDate: "descending"
          }
        }
      },
      {
        id: true,
        name: true,
        url: true,
        type: true,
        folders: true,
        createdDate: true
      }
    ]
  });

Response

{
  "data": {
    "assets": [
      {
        "id": "...",
        "name": "My Icon",
        "url": "...",
        "type": "image/svg+xml",
        "folders": ["folder-id-1"],
        "createdDate": "2024-01-15T10:30:00Z"
      }
    ]
  }
}

Common asset types:

image/jpeg: jpeg images

image/png: png images

image/svg+xml: svg images

image/gif: gif images

image/webp: webp images

video/mp4: mp4 videos

application/pdf: pdf documents

To filter assets by folder, use the folders field with the folder ID. Assets can belong to multiple folders, so folders is an array field.

Query

const response = await adminSDK
  .query({
    assets: [
      {
        input: {
          query: {
            folders: { $in: ["your-folder-id"] }
          },
          sort: {
            createdDate: "descending"
          }
        }
      },
      {
        id: true,
        name: true,
        url: true,
        type: true,
        folders: true,
        createdDate: true
      }
    ]
  });

Response

{
  "data": {
    "assets": [
      {
        "id": "...",
        "name": "Folder Asset",
        "url": "...",
        "type": "image/png",
        "folders": ["your-folder-id"],
        "createdDate": "2024-01-15T10:30:00Z"
      }
    ]
  }
}

You can combine multiple filters to get more specific results. For example, to get all SVG images from a specific folder:

Query

const response = await adminSDK
  .query({
    assets: [
      {
        input: {
          query: {
            type: { $eq: "image/svg+xml" },
            folders: { $in: ["your-folder-id"] }
          },
          sort: {
            createdDate: "descending"
          },
          limit: 50
        }
      },
      {
        id: true,
        name: true,
        url: true,
        type: true,
        folders: true,
        createdDate: true
      }
    ]
  });

Response

{
  "data": {
    "assets": [
      {
        "id": "...",
        "name": "My SVG Icon",
        "url": "...",
        "type": "image/svg+xml",
        "folders": ["your-folder-id"],
        "createdDate": "2024-01-15T10:30:00Z"
      }
    ]
  }
}

Query

const input = {
  query: {
    type: { $eq: "image/svg+xml" },
    folders: { $in: ["your-folder-id"] }
  },
  sort: {
    createdDate: "descending"
  },
  limit: 20
};

const response = await adminSDK
  .query({
    assets: [
      { input },
      {
        id: true,
        name: true,
        url: true,
        type: true,
        folders: true,
        createdDate: true,
        bytes: true,
        lastUsed: true
      }
    ]
  });

$eq: equal

$ne: not equal

$in: in array

$nin: not in array

$exists: field exists

$regex: regular expression match

Example with multiple operators:

const response = await adminSDK
  .query({
    assets: [
      {
        input: {
          query: {
            type: { $in: ["image/jpeg", "image/png"] },
            name: { $regex: "logo" },
            folders: { $exists: true }
          }
        }
      },
      {
        id: true,
        name: true,
        url: true,
        type: true,
        folders: true
      }
    ]
  });

This query returns jpeg or png images that have "logo" in their name and belong to at least one folder.

Retrieve all users from a Builder Space.

To get all users from your Builder Space, use the following query.

Query

const response = await adminSDK
  .query({
    users: {
      id: true,
      name: true,
      email: true,
      role: true,
      lastActive: true
    }
  });

Response

{
  "data": {
    "users": [
      {
        "id": "...",
        "name": "Elena Aguilar",
        "email": "elena@builder.io",
        "role": "admin",
        "lastActive": 1746049078845
      },
      ...
    ]
  }
}

Clone your entire Builder Space by accessing details from a specific space and using that data to create a new Space.

For example, the following code selects 10 Models from your Space, returning the id, kind, and name. Use this data when creating a new Space programatically.

Query

const result = await adminSDK
  .chain.mutation.downloadClone({
    contentQuery: {
      limit: 10
    }
  })
  .execute();

Response

{
  "data": {
    "downloadClone": {
      "models": [
        // ...
      ]
    }
  }
}

To configure SSO providers through the Admin API, SSO must first be enabled for your space. For more details on SSO options, see SSO with your Identity Provider and Using Code Flow with SSO.

To set up a new SAML authentication provider within your space, use the following query.

const result = await adminSDK.chain.mutation.addSAMLProvider({
  settings: {
    displayName: "Company SSO",
    idpEntityId: "https://sso.company.com/entityId",
    ssoURL: "https://sso.company.com/login",
    x509Cert: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    rpEntityId: "https://www.builder.io"
  }
});

To set up an OIDC authentication provider within your space, use the following query.

const result = await adminSDK.chain.mutation.addOIDCProvider({
  settings: {
    displayName: "Company SSO",
    clientId: "https://sso.company.com/entityId",
    issuer: ""
  }
});

Add one or more webhooks to existing Spaces.

const result = await adminSDK
  .chain.mutation.updateWebhooks({
    webhooks: [
      {
        url: "https://webhook1.example.com/content-update",
        disablePayload: false,
        customHeaders: [
          {
            name: "Authorization",
            value: "Bearer token123"
          }
        ]
      },
      {
        url: "https://webhook2.example.com/notify",
        disablePayload: true,
        customHeaders: []
      }
    ]
  });

The following operations are to be used to query and manage an entire Builder Organization. Keep in mind that the Private API Key for an organization is different than the private key for a single Builder Space.

Duplicate a Space using either the source Space Private API Key or the parent root Organization Private Key. copySpace supports optional includeUsers and skipAssets flags.

This operation returns a newly generated private key for the duplicated Space. Store this key securely.

Query

const result = await adminSDK
  .chain.mutation.createSpace({
    settings: {
      name: "Development Environment",
      description: "Space for development and testing"
    }
  });

Response

{
  "data": {
    "createSpace": {
      "organization": {
        "name": "Dev Environment",
        "id": "...",
        "type": "space",
        ...
      },
      "privateKey": {
        ...
      }
    }
  }
}

When creating a Space, you can also directly add webhooks by adding a webhooks key and then following the same structure described within the Create a webhook section.

Duplicate a Space using either the source Space Private API Key or the parent root Organization Private API Key. Supports optional includeUsers and skipAssets flags and returns the new Space ID and its Private API Key. Requires Organization Admin permissions

Query

const result = await adminSDK
  .chain.mutation.copySpace({
    sourceSpaceId: "space-123",
    name: "My Duplicate Space",
    includeUsers: true,
    skipAssets: true
  })
  .execute();

Response

{
  "data": {
    "copySpace": {
      "newSpaceId": "generated-id",
      "privateKey": {
        "id": "bpk-generated",
        "key": "bpk-xyz...",
        "ownerId": "generated-id",
        "active": true,
        "name": "Auto generated"
      }
    }
  }
}

Create temporary tokens to embed specific Spaces within your organization, which is useful for embedding Builder content in other applications without exposing API keys.

Replace "your-space-id" with your Space's unique ID.

Query

const result = await adminSDK
  .chain.mutation.generateEmbedToken({
    claims: {
      spaceId: "your-space-id"
    }
  });

Use the GraphQL Explorer to try out these queries with your own Space and Organization. Then, visit the Admin API GraphQL Schema for more details on how to modify your queries.

Was this article helpful?