Query a pipe's snapshots, download the stored JSON, and follow the change-management operations run against it.
BETA - This API is currently in beta testing. If you encounter issues or have feedback, contact our support team.
Before You Begin
🔗 Use the GraphQL Playground to execute the queries in this guide.
➡️ New to GraphQL? Learn how to navigate the Playground with our Playground Basics Guide.
Prerequisites
- Authentication: Use a Service Account token (Personal Access Tokens are deprecated).
- Permissions: Your token must have
Admin(manage) permission on the target pipe. All three fields in this guide require it. - Pipe ID: The ID of the pipe you want to inspect. See Get resource IDs.
- At least one snapshot: Snapshots are created on demand, so a pipe that was never snapshotted returns nothing. Create one with Create a Pipe Snapshot.
Step 1: Read the Latest Snapshot
snapshot returns a single snapshot of the pipe. Called with no argument it returns the pipe's latest uploaded snapshot, which is the one a restore can target.
query {
pipe(id: 123) {
snapshot {
id
versionId
label
sequenceIndex
status
metrics
signedUrl
uploadedAt
createdAt
createdBy {
id
name
}
}
}
}
Sample Response:
{
"data": {
"pipe": {
"snapshot": {
"id": "456",
"versionId": "9f1c2d34-5678-49ab-bcde-0123456789ab",
"label": "Before the Q3 automation rework",
"sequenceIndex": 3,
"status": "UPLOADED",
"metrics": {
"entity_counts": { "phases": 5, "fields": 42, "automations": 3 },
"byte_size": 184320,
"compressed_byte_size": 20480
},
"signedUrl": "https://files.pipefy.com/org/org-uuid-here/repo_snapshots/pipe-uuid-here/9f1c2d34-5678-49ab-bcde-0123456789ab.json?signature=...",
"uploadedAt": "2026-06-25T12:35:01Z",
"createdAt": "2026-06-25T12:34:56Z",
"createdBy": { "id": "789", "name": "Ana Souza" }
}
}
}
}
A pipe with no uploaded snapshot returns snapshot: null, even when a PENDING or FAILED snapshot exists.
Step 2: Fetch One Specific Version
Pass versionId to address a snapshot directly. Unlike the no-argument form, this one returns the snapshot whatever its status, so it is how you poll a snapshot you just created until it reaches UPLOADED or FAILED.
query($id: ID!, $versionId: ID) {
pipe(id: $id) {
snapshot(versionId: $versionId) {
versionId
status
error
signedUrl
}
}
}
Query Variables:
{
"id": 123,
"versionId": "9f1c2d34-5678-49ab-bcde-0123456789ab"
}
A versionId that does not belong to this pipe returns snapshot: null.
Step 3: Page Through the Snapshot History
snapshots is a Relay connection listing every snapshot of the pipe, most recent first, including PENDING and FAILED ones. Use first and after to page.
query($id: ID!, $first: Int!, $after: String) {
pipe(id: $id) {
snapshots(first: $first, after: $after) {
edges {
cursor
node {
versionId
label
sequenceIndex
status
createdAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
Query Variables:
{
"id": 123,
"first": 2,
"after": null
}
Sample Response:
{
"data": {
"pipe": {
"snapshots": {
"edges": [
{
"cursor": "MQ",
"node": {
"versionId": "9f1c2d34-5678-49ab-bcde-0123456789ab",
"label": "Before the Q3 automation rework",
"sequenceIndex": 3,
"status": "UPLOADED",
"createdAt": "2026-06-25T12:34:56Z"
}
},
{
"cursor": "Mg",
"node": {
"versionId": "1a2b3c4d-5e6f-4789-abcd-ef0123456789",
"label": null,
"sequenceIndex": 2,
"status": "UPLOADED",
"createdAt": "2026-06-18T09:02:11Z"
}
}
],
"pageInfo": { "hasNextPage": true, "endCursor": "Mg" }
}
}
}
}
Feed endCursor back as after to fetch the next page, and stop when hasNextPage is false. See Pagination basics.
Step 4: Follow the Operations Run Against the Pipe
Structural operations on a pipe (a restore, a deploy, a sandbox version build) each get their own record with a kind, a status and, on failure, the reason. operations lists them, most recent first.
query {
pipe(id: 123) {
operations {
id
kind
status
error
createdAt
updatedAt
}
}
}
Sample Response:
{
"data": {
"pipe": {
"operations": [
{
"id": "9001",
"kind": "GENERATE_ENVIRONMENT",
"status": "RUNNING",
"error": null,
"createdAt": "2026-06-25T13:00:00Z",
"updatedAt": "2026-06-25T13:00:04Z"
},
{
"id": "8874",
"kind": "RESTORE",
"status": "FAILED",
"error": "the version could not be restored because it conflicts with the current Pipe (for example, two fields in the same phase would end up with the same name)",
"createdAt": "2026-06-24T18:20:00Z",
"updatedAt": "2026-06-24T18:21:37Z"
}
]
}
}
}
- Failed restores: a restore that conflicts with the current pipe (for example, two fields in one phase ending up with the same name) fails on its first attempt and unlocks the pipe right away.
To check whether anything is under way right now, filter by status:
query {
pipe(id: 123) {
operations(status: [PENDING, RUNNING]) {
id
kind
status
}
}
}
An empty array means the pipe is idle, so a new restore or version build can be started.
Step 5: Read the Operations Sourced From One Snapshot
The reverse direction is available on the snapshot itself: operations on a snapshot lists the operations that used it as their source, most recent first, as a Relay connection.
query {
pipe(id: 123) {
snapshot {
versionId
operations {
nodes {
id
kind
status
error
}
}
}
}
}
This is how you confirm that the restore you requested with Restore a Pipe to a Snapshot actually finished: find the RESTORE operation on the snapshot you targeted and read its status.
Step 6: Tell Where Each Version Came From
Every version comes from one of three places: a restore, a Sandbox deploy, or a manual snapshot. Two fields on the snapshot tell them apart.
query {
pipe(id: 123) {
snapshots(first: 20) {
nodes {
sequenceIndex
restoredFromSnapshot {
sequenceIndex
versionId
}
repoVersion {
id
}
}
}
}
}
Sample Response:
{
"data": {
"pipe": {
"snapshots": {
"nodes": [
{
"sequenceIndex": 8,
"restoredFromSnapshot": { "sequenceIndex": 3, "versionId": "9f1c2d34-5678-49ab-bcde-0123456789ab" },
"repoVersion": null
},
{
"sequenceIndex": 7,
"restoredFromSnapshot": null,
"repoVersion": { "id": "55" }
},
{
"sequenceIndex": 6,
"restoredFromSnapshot": null,
"repoVersion": null
}
]
}
}
}
}
Version 8 was produced by restoring version 3, version 7 was published by deploying sandbox version 55, and version 6 was taken manually.
Response Fields
Snapshot
versionId: Unique identifier for the snapshot version. Use it to address one snapshot unambiguously insnapshot(versionId:),renameRepoSnapshotandrestoreRepoToSnapshot.sequenceIndex: Monotonic per-pipe ordering position among uploaded snapshots, starting at 1. Assigned on upload, so it isnullwhilePENDINGand staysnullfor a snapshot thatFAILED. The highest one is the pipe's latest snapshot.label: Human-readable name set throughrenameRepoSnapshot.nullfor snapshots that were never named.status:PENDING(queued, generation unfinished),UPLOADED(stored,signedUrlavailable) orFAILED(generation failed permanently, seeerror).metrics:entity_counts,byte_sizeandcompressed_byte_size. Empty ({}) whilePENDING.signedUrl: Temporary pre-signed URL to download the snapshot JSON.nulluntil the snapshot isUPLOADED, and it expires, so fetch it when you are about to download rather than storing it.createdBy: The user who requested the snapshot.nullfor snapshots taken before authorship was recorded and for authors whose account was anonymized.restoredFromSnapshot: The version this snapshot was restored from, when a restore produced it.nullotherwise.repoVersion: The sandbox version whose deploy published this snapshot.nullfor a manual or restored snapshot, and for a snapshot a sandbox was only cloned from.
Operation
kind:RESTORE(pipe structure reconciled to a snapshot),DEPLOY(a version deployed onto the pipe) orGENERATE_ENVIRONMENT(an editable sandbox version built by cloning the pipe from a snapshot).status:PENDING(queued),RUNNING(executing),SUCCEEDEDorFAILED.error: Why the operation failed.nullunlessstatusisFAILED.
Key Notes
- Admin only: all three fields authorize
Admin(manage) on the pipe. A token without it receives aPERMISSION_DENIEDerror and the field resolves tonull, so a member cannot discover that a pipe has snapshots at all. snapshotwith no argument skips unfinished snapshots: it returns the latestUPLOADEDsnapshot only. PassversionIdto read aPENDINGorFAILEDone.snapshotsincludes every status: the list is unfiltered, so a failed generation shows up there with itserror. Filter client-side onstatusif you only want usable snapshots.- Cursors are positional: a snapshot created while you page through the list shifts the window, so one row can repeat or be skipped. Page through the history in one go rather than holding a cursor across a long interval.
operationsis not paginated: it returns a plain list of every matching operation, so use thestatusargument to keep the response bounded.- Related operations: Create a Pipe Snapshot, Rename a Pipe Snapshot, Restore a Pipe to a Snapshot and Open a Pipe Sandbox Version.

