For AI agents: an index of this documentation is at https://developer.rippling.com/llms.txt. Public pages have a Markdown version at the same URL with .md added.

Skip to main content
guide

Create and manage sites

Use the Sites API to create, update, and delete sites and their files in Rippling.

Use with AI:Rippling AI ChatGPT Claude Cursor

Overview​

Sites host browser-based tools inside Rippling, such as dashboards, calculators, and interactive guides. You can build a site with Rippling AI or upload HTML, CSS, and JavaScript that you built with another tool. Each site runs at app.rippling.com/sites/<api_name>, and only the people you give access can see it.

Use the Sites API to create and update sites from code, a function, or an AI agent. A site can also call the Rippling Platform APIs to read and write Rippling data.

Use a site when you need a flexible, polished experience, like a guide, calculator, or executive readout. Use a custom app when you need structured records, forms, approvals, and role-based permissions.

Key terms:

  • Site: A web app hosted in Rippling. A site is a single .html file or a set of files with an entry page, usually index.html.
  • API name: The unique identifier for a site, used in its URL and in API requests. You set it when you create a site with the API. In Site Manager, Rippling generates it from the display name.
  • Display name: The name people see in the Rippling sidebar and search results. The API returns it as name.
  • Bundle: The set of files that's live on a site. Each site has one active bundle, identified by current_bundle_id. Each time you replace or change the files, Rippling creates a new bundle.
  • Staged upload: Files you've uploaded but haven't attached to a site yet. Each staged upload has a file_id and expires 1 hour after you presign it.
  • Entry path: The page that loads first when someone opens the site. Defaults to index.html.
  • Admins and Viewers: The groups that can edit and view the site.

Available endpoints​

EndpointDescription
GET List sitesReturns the sites you can view or edit.
GET Retrieve a specific siteReturns one site by its API name.
POST Create a presigned staged upload batchReturns upload URLs for your site files.
POST Create a new siteCreates a site from a staged upload.
PATCH Update a siteUpdates a site's details or replaces all of its files.
GET List files in the active bundleReturns the files and folders in a site.
POST Apply file operations to a site bundleAdds, renames, moves, or deletes individual files and folders.
DELETE Delete a siteDeletes a site.

Suggested workflow​

  1. Call POST Create a presigned staged upload batch to get an upload URL.
  2. Upload your .html or .zip file to that URL.
  3. Call POST Create a new site with the file_id from step 1.
  4. To change the site later, call PATCH Update a site or POST Apply file operations to a site bundle.
  5. Call DELETE Delete a site when you no longer need it.

Requirements​

  • Rippling AI. Companies with Rippling AI automatically get access to the Rippling APIs, including the Sites API.
  • An API token with the following scopes:
    • sites.read to fetch sites and their files
    • sites.read-write to create, update, and delete sites and their files

Fetch​

List sites​

Use GET List sites to return the sites you have view or edit access to. Results are paginated.

Request:

curl -L -X GET 'https://rest.ripplingapis.com/sites/?limit=50' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer REDACTED'

Response:

{
"__meta": {
"redacted_fields": []
},
"results": [
{
"id": "6748f1a2b3c4d5e6f7a8b9c0",
"name": "Employee Handbook",
"description": "Searchable company handbook",
"api_name": "employee_handbook",
"logo": null,
"current_bundle_id": "6748f1a2b3c4d5e6f7a8b9d1",
"admin_group_id": "6748f1a2b3c4d5e6f7a8b9e2",
"viewer_group_id": "6748f1a2b3c4d5e6f7a8b9f3",
"created_by": "6748f1a2b3c4d5e6f7a8ba04",
"created_at": "2026-10-22T14:30:00Z"
}
],
"next_link": null
}
Response fieldDescription
__meta.redacted_fieldsFields removed from the response because you don't have permission to see them.
results[].idThe site's ID.
results[].nameThe site's display name.
results[].descriptionThe site's description, if it has one.
results[].api_nameThe site's unique API name, used in its URL.
results[].logoThe URL of the site's logo, hosted by Rippling.
results[].current_bundle_idThe ID of the site's active bundle.
results[].admin_group_idThe ID of the group that can edit the site.
results[].viewer_group_idThe ID of the group that can view the site.
results[].created_byThe ID of the role that created the site.
results[].created_atThe date and time the site was created.
next_linkA link to the next page of results. null on the last page.

Retrieve a site​

Use GET Retrieve a specific site to return one site by its API name. The name filter on List sites matches any part of the display name, so use this endpoint when you need one exact site.

Request:

curl -L -X GET 'https://rest.ripplingapis.com/sites/employee_handbook/' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer REDACTED'

Response:

{
"id": "6748f1a2b3c4d5e6f7a8b9c0",
"name": "Employee Handbook",
"description": "Searchable company handbook",
"api_name": "employee_handbook",
"logo": null,
"current_bundle_id": "6748f1a2b3c4d5e6f7a8b9d1",
"admin_group_id": "6748f1a2b3c4d5e6f7a8b9e2",
"viewer_group_id": "6748f1a2b3c4d5e6f7a8b9f3",
"created_by": "6748f1a2b3c4d5e6f7a8ba04",
"created_at": "2026-10-22T14:30:00Z"
}

The fields are the same as a result in List sites.

List a site's files​

Use GET List files in the active bundle to return the files and folders in a site's active bundle.

Request:

curl -L -X GET 'https://rest.ripplingapis.com/sites/employee_handbook/files/?recursive=true' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer REDACTED'

Response:

{
"bundle_id": "6748f1a2b3c4d5e6f7a8b9d1",
"entry_path": "index.html",
"parent_path": "",
"recursive": true,
"files": [
{
"path": "index.html",
"name": "index.html",
"parent_path": "",
"content_type": "text/html",
"size_bytes": 13517,
"sha256": "9f2c4e1b7a..."
},
{
"path": "assets/app.css",
"name": "app.css",
"parent_path": "assets",
"content_type": "text/css",
"size_bytes": 9420,
"sha256": "4b7d0a93e2..."
}
],
"directories": [
{
"path": "assets",
"name": "assets",
"parent_path": ""
}
]
}
Response fieldDescription
bundle_idThe ID of the active bundle. Use it as base_bundle_id when you change files.
entry_pathThe page that loads first.
parent_pathThe folder that was listed.
recursiveWhether subfolders were included.
files[].pathThe file's full path in the site.
files[].nameThe file's name.
files[].parent_pathThe folder the file is in.
files[].content_typeThe file's media type, like text/html.
files[].size_bytesThe file's size in bytes.
files[].sha256A SHA-256 hash of the file's contents. Use it to check whether a file changed.
directories[].pathThe folder's full path.
directories[].nameThe folder's name.
directories[].parent_pathThe folder it's inside.

Create​

Creating a site takes three steps: get an upload URL, upload your file to it, and then create the site.

A site can include HTML, CSS, and JavaScript files, plus other assets like images and PDFs. A site can be up to 25 MB and include up to 200 files. If you upload a .zip without an index.html file, set entry_path to the page that should load first. In Site Manager, the upload fails with "Entry path index.html was not found."

Get an upload URL​

Use POST Create a presigned staged upload batch to get a URL for each file you plan to upload. You use this same step to create a site, replace a site's files, or add a file.

Request:

curl -L -X POST 'https://rest.ripplingapis.com/sites/upload-batches/presign/' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer REDACTED'

Request body:

{
"file_intents": [
{
"client_ref": "handbook-upload-1",
"file_name": "site.zip"
}
]
}
Request body fieldRequiredDescription
file_intentsYesThe files you plan to upload.
file_intents[].client_refYesAny unique ID you choose, so you can match each file to its upload URL.
file_intents[].file_nameYesThe file's name, like site.zip or index.html.

Response:

{
"upload_batch_id": "6748f1a2b3c4d5e6f7a8bb00",
"files": [
{
"client_ref": "handbook-upload-1",
"file_id": "6748f1a2b3c4d5e6f7a8bb15",
"file_name": "site.zip",
"upload_url": "https://example-bucket.s3.amazonaws.com/",
"upload_fields": {
"key": "staged/6748f1a2b3c4d5e6f7a8bb15/site.zip",
"policy": "REDACTED",
"x-amz-signature": "REDACTED"
}
}
]
}
Response fieldDescription
upload_batch_idThe ID of the staged upload batch. You don't use it in later calls.
files[].client_refThe client_ref you sent, so you can match each file.
files[].file_idThe staged upload ID. Use it to create or update the site.
files[].file_nameThe file name you sent.
files[].statusThe upload's status.
files[].upload_urlThe URL to upload the file to.
files[].upload_fieldsThe form fields to send with the upload. The fields can vary, so send all of them exactly as returned.
Use file_id, not upload_batch_id

Pass files[].file_id to the create, update, and file operations endpoints. Passing upload_batch_id doesn't work.

Upload the file​

Send a multipart POST to upload_url. Include every field from upload_fields, and then add the file as the last part. This request goes straight to storage, so don't include your Rippling token.

curl -L -X POST 'https://example-bucket.s3.amazonaws.com/' \
-F 'key=staged/6748f1a2b3c4d5e6f7a8bb15/site.zip' \
-F 'policy=REDACTED' \
-F 'x-amz-signature=REDACTED' \
-F 'file=@site.zip'

Create the site​

Use POST Create a new site to create the site from your staged upload.

Request:

curl -L -X POST 'https://rest.ripplingapis.com/sites/' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer REDACTED'

Request body:

{
"name": "Employee Handbook",
"description": "Searchable company handbook",
"api_name": "employee_handbook",
"file_id": "6748f1a2b3c4d5e6f7a8bb15"
}
Request body fieldRequiredDescription
nameYesThe site's display name.
api_nameYesThe site's unique API name, used in its URL.
file_idYesThe staged upload ID from the presign response.
descriptionNoA description of the site.
logoNoA Rippling-hosted logo URL.
entry_pathNoThe page that loads first, like home.html. Required if your .zip doesn't include index.html.

Response:

{
"id": "6748f1a2b3c4d5e6f7a8b9c0",
"name": "Employee Handbook",
"description": "Searchable company handbook",
"api_name": "employee_handbook",
"logo": null,
"current_bundle_id": "6748f1a2b3c4d5e6f7a8b9d1",
"admin_group_id": "6748f1a2b3c4d5e6f7a8b9e2",
"viewer_group_id": "6748f1a2b3c4d5e6f7a8b9f3",
"created_by": "6748f1a2b3c4d5e6f7a8ba04",
"created_at": "2026-10-27T10:30:00Z"
}

The fields are the same as a result in List sites.

Reusing a staged upload

You can use the same file_id for up to 1 hour after you presign it. Each time you use it, Rippling copies the files into a new bundle. After an hour, the staged upload is deleted.


Update​

Update a site's details​

Use PATCH Update a site to change a site's name, description, or logo. You don't need to upload anything for these changes.

Request:

curl -L -X PATCH 'https://rest.ripplingapis.com/sites/employee_handbook/' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer REDACTED'

Request body:

{
"name": "Employee Handbook 2027",
"description": "Updated for the new year"
}
Request body fieldRequiredDescription
nameNoThe site's new display name.
descriptionNoThe site's new description.
logoNoA new Rippling-hosted logo URL.
file_idNoA staged upload ID. Replaces all of the site's files.
entry_pathNoThe page that loads first. Required with file_id if the new .zip doesn't include index.html.

Response:

{
"id": "6748f1a2b3c4d5e6f7a8b9c0",
"name": "Employee Handbook 2027",
"description": "Updated for the new year",
"api_name": "employee_handbook",
"logo": null,
"current_bundle_id": "6748f1a2b3c4d5e6f7a8b9d1",
"admin_group_id": "6748f1a2b3c4d5e6f7a8b9e2",
"viewer_group_id": "6748f1a2b3c4d5e6f7a8b9f3",
"created_by": "6748f1a2b3c4d5e6f7a8ba04",
"created_at": "2026-10-22T14:30:00Z"
}

The fields are the same as a result in List sites.

Replace all of a site's files​

To replace the whole site, get an upload URL, upload the file, and then call PATCH Update a site with the new file_id:

{
"file_id": "6748f1a2b3c4d5e6f7a8bb27"
}

Everyone with access sees the new version right away.

Change individual files​

Use POST Apply file operations to a site bundle to add, rename, move, or delete specific files and folders. All operations in one request succeed or fail together.

To add or replace a file, get an upload URL and upload the file first, then use its file_id in a put operation.

Request:

curl -L -X POST 'https://rest.ripplingapis.com/sites/employee_handbook/file-operations/' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer REDACTED'

Request body:

{
"base_bundle_id": "6748f1a2b3c4d5e6f7a8b9d1",
"operations": [
{
"op": "put",
"kind": "file",
"path": "assets/logo.png",
"file_id": "6748f1a2b3c4d5e6f7a8bb31"
},
{
"op": "rename",
"kind": "file",
"from_path": "about.html",
"to_path": "team.html"
},
{
"op": "delete",
"kind": "directory",
"path": "old-assets",
"recursive": true
}
]
}
Request body fieldRequiredDescription
base_bundle_idYesThe site's current_bundle_id.
operationsYesThe changes to make. Must include at least one.
operations[].opYesput, rename, move, or delete. Folders support put, rename, and delete, but not move.
operations[].kindYesfile or directory.
operations[].pathFor put and deleteThe path of the file or folder.
operations[].file_idFor put on a fileThe staged upload ID for the file.
operations[].from_pathFor rename and moveThe current path.
operations[].to_pathFor rename and moveThe new path.
operations[].recursiveNoFor deleting a folder. Set to true to delete everything inside it.
entry_pathNoA new entry page. If you leave it out, the current one stays.

Response:

{
"id": "6748f1a2b3c4d5e6f7a8b9c0",
"name": "Employee Handbook",
"description": "Searchable company handbook",
"api_name": "employee_handbook",
"logo": null,
"current_bundle_id": "6748f1a2b3c4d5e6f7a8b9e7",
"admin_group_id": "6748f1a2b3c4d5e6f7a8b9e2",
"viewer_group_id": "6748f1a2b3c4d5e6f7a8b9f3",
"created_by": "6748f1a2b3c4d5e6f7a8ba04",
"created_at": "2026-10-22T14:30:00Z"
}

The response is the updated site, including its new current_bundle_id.

Use the current bundle ID

If base_bundle_id doesn't match the site's current bundle, the request returns 409. This happens when someone else changed the site after you fetched it. Get the latest current_bundle_id and try again.


Delete​

Use DELETE Delete a site to delete a site.

Request:

curl -L -X DELETE 'https://rest.ripplingapis.com/sites/employee_handbook/' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer REDACTED'

A successful delete returns 204 No Content with no response body.


Use cases​

Call Rippling APIs from a site​

A site can read and write Rippling data through the Platform APIs. Each viewer only sees the data their own Rippling permissions allow. For example, a manager viewing a compensation benchmarking site only sees compensation for their direct reports. Data saved in the site's files, like hard-coded values or a bundled CSV, isn't filtered. Every viewer can see it.

A site can only use fields that the Rippling REST APIs expose. Before you build a site around a field, check that the field is available in the relevant API and that it returns the right data for each viewer. There are no cross-origin resource sharing (CORS) limits on calls from a site to rest.ripplingapis.com.

A site that calls POST, PATCH, or DELETE endpoints changes live data in Rippling. Before the call goes through, the viewer sees a consent notice and must click I understand. The notice tells them the site can change live data and can only use permissions they already have. If they click Go back, the notice closes and the request isn't sent. Viewers see the notice once for each version of the site. If you update a site and it still makes write calls, viewers see the notice again.

To build a site that writes data, you need the Sites creator with write API access permission. Everyone has it by default, and admins can remove it in the Permissions app. A site can only write if the person who created it or last updated it has this permission.

Write actions use the viewer's permissions

A site can't do anything the viewer couldn't do in Rippling themselves. If a viewer doesn't have permission to update a record, the site can't update it for them.

You don't create or store a token for this. When someone views your site, Rippling handles authentication for every fetch or XMLHttpRequest call the site makes to rest.ripplingapis.com. It creates a token for the viewer, sends the request, and returns the response to your site.

  1. Call the endpoints your site needs with a standard fetch call to https://rest.ripplingapis.com. Don't add an Authorization header.
  2. Handle errors for calls the viewer doesn't have permission to make.
  3. (Optional) To show information about the viewer, such as their work email, call GET Retrieve my SSO information.

Customize the following code for your setup:

async function listWorkers() {
const response = await fetch('https://rest.ripplingapis.com/workers/?limit=50', {
headers: { Accept: 'application/json' },
});

if (!response.ok) {
throw new Error(`Couldn't load workers: ${response.status}`);
}

const data = await response.json();
return data.results;
}

listWorkers().then((workers) => {
const list = document.querySelector('#workers');
for (const worker of workers) {
const item = document.createElement('li');
item.textContent = worker.work_email;
list.append(item);
}
});

Rippling only handles authentication when the site is viewed at app.rippling.com/sites/<api_name>. If you open the site's files directly on your computer, its API calls fail. Use sample data while you build, then test API calls after you upload the site.

Don't add your own token

Never put an API token in a site's HTML or JavaScript. Anyone who can view the site can read its code. Rippling replaces any token you add with the viewer's, so it doesn't change what the site can do.

Deploy a site from a function or agent​

  1. Build the site files with your coding agent or a function.
  2. The first time, get an upload URL, upload the files, and create the site.
  3. After that, replace all of the site's files or change individual files.

Limits​

Sites run in a sandboxed frame inside Rippling, which limits what they can do:

  • Open external pages inside the site. Links to other websites need to open in a new tab, for example with target="_blank".
  • Load content from other websites. A site can't call APIs or load images from other domains, such as map tiles.
  • Read the query string. A site can't read the query parameters in the Rippling URL.
  • Store data in the browser. localStorage, sessionStorage, and cookies aren't available. Code that uses them throws an error.
  • Use any image, font, or audio source. Images can use blob: and data: URLs. Fonts can use data: URLs only. Audio from blob: and data: URLs doesn't play.
  • Manage sites. A site can't call the Sites API. Those requests return 403.
  • Launch from an app tile. Sites appear in the Sites section of the sidebar.
  • Ship in a package. You can't include a site in a distributable package.

The Sites API has no endpoint-specific rate limits. It follows the standard API limits: 600 requests per 10 seconds per token for each endpoint path. If you go over, the API returns 429 Too Many Requests. Retry with exponential backoff or the Retry-After header.


See also​